zoukankan      html  css  js  c++  java
  • P2045 方格取数加强版 题解

    题目描述

    给出一个(N imes N)的矩阵,每一格有一个非负整数(a[i][j])每次走过时可以取出这个数,走过多次只算一次,求走(k)次取得的最大代价

    问题求解

    如果(k=1)的话,显然可以用(DP)来解决,但是(k>1)时前一种的走法对下一次产生了影响,所以考虑用网络流来做

    把每个点看成是一个入点和一个出点,每个格子,我们可以从入点到出点建一条流量为(1),费用为(a[i][j])的边,和(k-1)条流量为(k-1),费用为(0)的边,表示一个数的代价只算一次,为了保证图的连通性,讲(i,j)向边上建流量为(k),费用为(0)的边

    最后答案就是从((1,1))的入点到((n,n))的出点的最大流

    代码实现

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=5010,maxe=maxn*8,INF=0x3f3f3f3f;
    int N,K,mp[55][55],T;
    int lnk[maxn],nxt[maxe],son[maxe],w[maxe],cost[maxe],cnt=1,vis[maxn],cur[maxn],Q[maxn],dis[maxn];
    int maxflow,mincost,st,ed;
    inline int read(){
    	int ret=0,f=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-f;ch=getchar();}
    	while(ch<='9'&&ch>='0')ret=ret*10+ch-'0',ch=getchar();
    	return ret*f;
    }
    void add_e(int x,int y,int z,int c){son[++cnt]=y;nxt[cnt]=lnk[x];lnk[x]=cnt;w[cnt]=z;cost[cnt]=c;}
    void add_edge(int x,int y,int z,int c){add_e(x,y,z,c);add_e(y,x,0,-c);}
    inline int calc(int x,int y){return N*(x-1)+y;}
    int spfa(){
    	int hed=0,til=1;Q[til]=st;
    	memset(dis,INF,sizeof dis);dis[st]=0;
    	while(hed!=til){
    		hed=(hed+1)%maxn;vis[Q[hed]]=0;
    		for(int j=lnk[Q[hed]];j;j=nxt[j]){
    			if(w[j]>0&&dis[son[j]]>dis[Q[hed]]+cost[j]){
    				dis[son[j]]=dis[Q[hed]]+cost[j];
    				if(!vis[son[j]]){
    					vis[son[j]]=1;Q[til=(til+1)%maxn]=son[j];
    				}
    			}
    		}
    	}
    	return dis[ed]!=INF;
    }
    int DFS(int x,int delta){
    	if(x==ed)return delta;
    	int flow=0;vis[x]=1;
    	for(int j=cur[x];j;j=nxt[j]){
    		if(!vis[son[j]]&&w[j]&&dis[son[j]]==dis[x]+cost[j]){
    			cur[x]=j;
    			int t=DFS(son[j],min(delta-flow,w[j]));
    			flow+=t;w[j]-=t;w[j^1]+=t;mincost+=t*cost[j];
    			if(flow==delta)break;
    		}
    	}
    	vis[x]=0;
    	return flow;
    }
    void Dinic(){
    	while(spfa()){
    		memcpy(cur,lnk,sizeof cur);
    		int tmp=DFS(st,INF);
    		if(!tmp)break;
    		maxflow+=tmp;
    	}
    }
    int main(){
    	N=read();K=read();T=N*N;
    	for(int i=1;i<=N;i++)for(int j=1;j<=N;j++)mp[i][j]=read();
    	st=1;ed=2*T;
    	for(int i=1;i<=N;i++)
    	for(int j=1;j<=N;j++){
    		add_edge(calc(i,j),calc(i,j)+T,1,-mp[i][j]);
    		add_edge(calc(i,j),calc(i,j)+T,K-1,0);
    		if(i<N)add_edge(calc(i,j)+T,calc(i+1,j),K,0);
    		if(j<N)add_edge(calc(i,j)+T,calc(i,j+1),K,0);
    	}
    	Dinic();
    	printf("%d
    ",-mincost);
    	return 0;
    }
    
  • 相关阅读:
    Three.js基础探寻六——文字形状与自定义形状
    Three.js基础探寻五——正二十面体、圆环面等
    Three.js基础探寻四——立方体、平面与球体
    Three.js基础探寻三——透视投影照相机
    Three.js基础探寻二——正交投影照相机
    Three.js基础探寻一
    js 基础 函数传值
    jQuery 判断页面元素是否存在的代码
    手机端点解链接有外框的问题
    团队博客冲刺第七天
  • 原文地址:https://www.cnblogs.com/martian148/p/15184893.html
Copyright © 2011-2022 走看看