• 棋盘


    简单题
    快速计算摆放棋子攻击对数的方法:拿出每个行/列连续段,设它有(p)个点。
    (ans+=frac{p(p+1)}{2})
    一个棋子会让它所在的行/列连续段贡献+1。
    用一条路径进行限制。
    (frac{p(p+1)}{2})可以拆边。
    具体看代码。
    做了这么久发现看错题了,口可

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    #define N 1200010
    int h[N],nxt[N],v[N],ct,w[N],s,t,pre[N],dis[N],pa[N],ec,q,co[N],inq[N],n,ans[N],i1[100][100],i2[100][100],c1,ss[N],ok[N];
    char st[100][100];
    struct no{
    	int a,b,c,d;
    };
    vector<no>vc;
    void add(int a,int b,int c,int d){
    	v[++ec]=b;w[ec]=c;nxt[ec]=h[a];co[ec]=d;h[a]=ec;
    }
    void adj(int a,int b,int c,int d){
    	add(a,b,c,d);
    	add(b,a,0,-d);
    }
    bool bfs(){
    	for(int i=0;i<=t;i++){
    		dis[i]=999999999;
    		pre[i]=-1;
    	}
        dis[s]=0;
    	queue<int>q;
    	q.push(s);
    	inq[s]=1;
    	while(!q.empty()){
        	int x=q.front();
    		q.pop();
    		inq[x]=0;
        	for(int i=h[x];i;i=nxt[i])
        		if(w[i]>0&&co[i]+dis[x]<dis[v[i]]){
        			dis[v[i]]=co[i]+dis[x];
    				pa[v[i]]=i;
        			pre[v[i]]=x;
    				if(!inq[v[i]]){
    					inq[v[i]]=1;
    					q.push(v[i]);
    				}
    			}
    	}
    	if(pre[t]==-1)
    		return false;
    	return true;
    }
    int mcmf(){
        int c=0,f=0;
    	while(bfs()){
        	int fl=1e9;
    		for(int i=t;s!=i;i=pre[i])
        		fl=min(fl,w[pa[i]]);
        	f+=fl;
    		c+=fl*dis[t];
    		ans[f]=c;
        	for(int i=t;i!=s;i=pre[i])
        		w[pa[i]]-=fl,w[pa[i]^1]+=fl;
    	}
    	return c;
    }
    signed main(){
    	ec=1;
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++)
    		scanf("%s",st[i]+1);
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=n;j++){
    			if(st[i][j]=='.'){
    				if(!i1[i][j-1])
    					i1[i][j]=++c1;
    				else
    					i1[i][j]=i1[i][j-1];
    				if(!i2[i-1][j]){
    					i2[i][j]=++c1;
    					ok[c1]=1;
    				}
    				else
    					i2[i][j]=i2[i-1][j];
    			}
    		}
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=n;j++){
    			ss[i1[i][j]]++;
    			ss[i2[i][j]]++;
    		}
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=n;j++)
    			if(st[i][j]!='#'){
    				adj(i1[i][j],i2[i][j],1,0);
    			}
    	t=c1+1;
    	for(int i=1;i<=c1;i++)
    		for(int j=0;j<ss[i];j++){
    			if(!ok[i])
    				adj(s,i,1,j);
    			else
    				adj(i,t,1,j);
    		}
    	mcmf();
    	scanf("%d",&q);
    	for(int i=1;i<=q;i++){
    		int x;
    		scanf("%d",&x);
    		printf("%d
    ",ans[x]);
    	}
    }
    
  • 相关阅读:
    colemak,你用了吗?
    DELPHI一个对付内存汇漏的办法和技巧
    使用for in 循环数据集
    今天差点被断电搞死了,幸好IDE的备份救了我
    为什么继续选择DELPHI?
    无缘DELPHI的BUG
    DELPHI DOUBLE不解之迷
    失败的大牛事件委托,与我的委托
    2017-02-08 01:19:09 Scrapy: pk5_mylist
    2016-09-02 16:50:15 webqq 协议分析
  • 原文地址:https://www.cnblogs.com/ctmlpfs/p/14969942.html
Copyright © 2020-2023  润新知