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;
    }
    
    
  • 相关阅读:
    python爬虫-selenium八大定位笔记
    git pull : error: cannot lock ref 'refs/remotes/origin/*' (unable to update local ref) 解决方案
    Lua table.sort()原理和使用的坑
    Unity---有关游戏物体角度的两种赋值方法这件事
    C# #if、#endif和预处理指令
    Unity 4大坐标系 和 屏幕坐标与UI坐标的转换问题
    第2次参加游戏开发比赛
    Unity Text添加空格导致换行问题的两种解决方法(还有lua的解决方法)
    MySQL是如何处理千万级数据
    PHP使用守护进程处理队列
  • 原文地址:https://www.cnblogs.com/PPXppx/p/11614185.html
Copyright © 2011-2022 走看看