zoukankan      html  css  js  c++  java
  • Kaka's Matrix Travels

    POJ

    洛咕

    给出一个(n*n)的矩阵,每一格有一个非负整数(A_{i,j},(A_{i,j} <= 1000)),现在从((1,1))出发,可以往右或者往下走,最后到达((n,n)),每达到一格,把该格子的数取出来,该格子的数就变成(0),这样一共走(K)次,现在要求(K)次所达到的方格的数的和最大.((1<=n<=50, 0<=k<=10).)

    分析:构建费用流模型(点边转化,拆点法).每个格子((i,j))对应一个节点((i-1)*n+j),拆成一个入点和一个出点,入点向出点连两条有向边,一条容量为1,费用为格子((i,j))中的数(表示第一次经过该点是把数取走);另一条容量(k-1),费用为(0)(表示之后再经过该点时,不能再取数了).((i,j))的出点还要向((i,j+1))((i+1,j))的入点连有向边,容量为(k),费用为(0)(怎么走都不会有取数).

    然后以((1,1))为源点,((n,n))为汇点,求最大费用最大流即可.

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<map>
    #include<set>
    #define ll long long
    using namespace std;
    inline int read(){
        int x=0,o=1;char ch=getchar();
        while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
        if(ch=='-')o=-1,ch=getchar();
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x*o;
    }
    const int N=200005;//懒得想数组具体要开多大了
    int n,k,s,t,max_flow,ans;
    int dis[N],visit[N],pre[N],incf[N];
    int tot,head[N],nxt[N],to[N],limit[N],w[N];
    inline void add(int a,int b,int c,int d){
    	nxt[++tot]=head[a];head[a]=tot;
    	to[tot]=b;limit[tot]=c;w[tot]=d;
    	nxt[++tot]=head[b];head[b]=tot;
    	to[tot]=a;limit[tot]=0;w[tot]=-d;
    }
    inline bool spfa(){
    	for(int i=1;i<N;++i)dis[i]=-1e9,visit[i]=0;
    	queue<int>q;q.push(s);dis[s]=0;visit[s]=1;
    	incf[s]=1<<30;
    	while(q.size()){
    		int u=q.front();q.pop();visit[u]=0;
    		for(int i=head[u];i;i=nxt[i]){
    			if(!limit[i])continue;
    			int v=to[i];
    			if(dis[v]<dis[u]+w[i]){
    				dis[v]=dis[u]+w[i];
    				incf[v]=min(incf[u],limit[i]);
    				pre[v]=i;
    				if(!visit[v])visit[v]=1,q.push(v);
    			}
    		}
    	}
    	if(dis[t]==-1e9)return false;
    	return true;
    }
    inline void update(){
    	int x=t;
    	while(x!=s){
    		int i=pre[x];
    		limit[i]-=incf[t];
    		limit[i^1]+=incf[t];
    		x=to[i^1];
    	}
    	max_flow+=incf[t];
    	ans+=dis[t]*incf[t];
    }
    int main(){
    	n=read(),k=read();s=1;t=2*n*n;tot=1;
    	for(int i=1;i<=n;++i){
    		for(int j=1;j<=n;++j){
    			int val=read();
    			add((i-1)*n+j,(i-1)*n+j+n*n,1,val);
    			add((i-1)*n+j,(i-1)*n+j+n*n,k-1,0);
    			if(j+1<=n)add((i-1)*n+j+n*n,(i-1)*n+j+1,k,0);
    			if(i+1<=n)add((i-1)*n+j+n*n,i*n+j,k,0);
    		}
    	}
    	while(spfa())update();
    	printf("%d
    ",ans);
        return 0;
    }
    
    
  • 相关阅读:
    73. Set Matrix Zeroes
    289. Game of Live
    212. Word Search II
    79. Word Search
    142. Linked List Cycle II
    141. Linked List Cycle
    287. Find the Duplicate Number
    260. Single Number III
    137. Single Number II
    Oracle EBS中有关Form的触发器的执行顺序
  • 原文地址:https://www.cnblogs.com/PPXppx/p/11614185.html
Copyright © 2011-2022 走看看