题目链接:ヾ(≧∇≦*)ゝ

大致题意:给你一个\(n*n\)的矩阵从\((1,1)\)出发,到\((n,n)\)结束,只能走右边或左边。每个点在被走过之后权值变成0,问走\(k\)次后,能获得的最大值总和是多少

Solution:

看数据范围,\(n\le50,0\le k \le10\),再结合题目,一下子就能想到费用流

那么,该如何建图呢?

我们看一下限制:

首先,每一个点只能贡献一次价值,如何来解决这个问题呢?

拆点。把每个点分为入点和出点,入点和出点之间的费用为该点权值,容量为1,这样就能够解决这条限制。

然后,再把每一个点的出点与它右边的点的入点和下面的点的入点连边,费用为0,容量为k

再是能够走k次,我们建立一个超级源点和超级汇点,拿出发点的入点与源点连边,容量为k,费用为0,结束点的出点与汇点连边,容量为k,费用为0

不过,仅仅这样是不行的。按照上述的建图,我们发现它只能应对\(k\le2\)的情况,最多跑完两次最大费用流,它就会无路可走,所以我们还需要连一些边。

对于每一个点,将它的出点与它右边点的的出点,下面点的出点都连一条容量为k,费用为0的边。

这是什么意思呢?这条边代表只是经过这个点,而不取该点的权值。

最后跑最大费用流,拿答案减去多加的出发点和结束点的权值,就是答案了

不过,当\(k=0\)时,需要特判一下,直接输出0。(博主就是因为忘记特判而狂WA不止啊...)

Code:

#include<queue>
#include<cstdio>
#include<ctype.h>
#include<cstring>
#include<algorithm>
#define N 30001
#define inf 0x8f
using namespace std;
int S,T,n,k,cnt=1,tot;
int head[N],mp[51][51];
struct Edge{int nxt,to,v,w;}edge[N];
void ins(int x,int y,int z,int w){edge[++cnt].nxt=head[x];edge[cnt].to=y;edge[cnt].v=z;edge[cnt].w=w;head[x]=cnt;
}
namespace Network_Flow{queue<int> q;int maxcost,delta;int dis[N],vis[N],pre[N];int spfa(){pre[T]=0;delta=inf;memset(vis,0,sizeof(vis));memset(dis,255,sizeof(dis));q.push(S);vis[S]=1;dis[S]=0;while(!q.empty()){int x=q.front();q.pop();vis[x]=0;for(int i=head[x];i;i=edge[i].nxt){int y=edge[i].to;if(edge[i].v&&dis[x]+edge[i].w>dis[y]){dis[y]=dis[x]+edge[i].w;delta=min(delta,edge[i].v);pre[y]=i;if(!vis[y]) q.push(y),vis[y]=1;}}}return pre[T];}void update(){int x=T;while(x!=1){int i=pre[x];edge[i].v-=delta;edge[i^1].v+=delta;x=edge[i^1].to;}maxcost+=dis[T]*delta;}void Edmond_Karp(){while(spfa()) update();printf("%d\n",maxcost-(k-1)*(mp[1][1]+mp[n][n]));}
}
int num(int i,int j){return (i-1)*n*2+j*2;}
int read(){int x=0,f=1;char ch=getchar();while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}return x*f;
}
int main(){n=read(),k=read();S=n*n*2+1,T=S+1;using namespace Network_Flow;for(int i=1;i<=n;i++)for(int j=1;j<=n;j++){mp[i][j]=read();tot+=2;if((i==1&&j==1)||(i==n&&j==n)){ins(tot-1,tot,k,mp[i][j]);ins(tot,tot-1,0,-mp[i][j]);continue;}ins(tot-1,tot,1,mp[i][j]);ins(tot,tot-1,0,-mp[i][j]);}if(!k){printf("0");return 0;}ins(S,1,inf,0);ins(1,S,0,0);ins(tot,T,inf,0);ins(T,tot,0,0);for(int i=1;i<=n;i++)for(int j=1;j<=n;j++){if(i<n){ins(num(i,j),num(i+1,j)-1,k,0);ins(num(i+1,j)-1,num(i,j),0,0);ins(num(i,j),num(i+1,j),k,0);ins(num(i+1,j),num(i,j),0,0);}if(j<n){ins(num(i,j),num(i,j+1)-1,k,0);ins(num(i,j+1)-1,num(i,j),0,0);ins(num(i,j),num(i,j+1),k,0);ins(num(i,j+1),num(i,j),0,0);}}Edmond_Karp();return 0;
}

转载于:https://www.cnblogs.com/NLDQY/p/10333559.html

POJ 3422 Kaka's Matrix Travels相关推荐

  1. poj 3422 Kaka's Matrix Travels(最小费用最大流)

    题目链接 Kaka's Matrix Travels Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 9394   Accep ...

  2. POJ - 3422 Kaka's Matrix Travels(网络流-最大费用最大流+拆点法)

    题目链接:点击查看 题目大意:K取方格数,是在一个N*N的矩形网格中,每个格子里都写着一个整数.可以从左上角到右下角安排K条路线,每一步只能往下或往右,沿途经过的格子中的整数会被取走.若多条路线重复经 ...

  3. POJ 3422 Kaka's Matrix Travels | 费用流

    最初的想法是这样的,先走一条最大费用流,沿路回来把所有的点的权值更新为0,然后再跑最大费用流,嗯,好像很对.后来想想,这完全不符合网络流的思想啊Orz. 题意: 一个矩阵,每个grid都有一个权值.从 ...

  4. poj 3422 Kaka's Matrix Travels 费用流

    题目链接 给一个n*n的矩阵, 从左上角出发, 走到右下角, 然后在返回左上角,这样算两次. 一共重复k次, 每个格子有值, 问能够取得的最大值是多少, 一个格子的值只能取一次, 取完后变为0. 费用 ...

  5. pku 3422 Kaka's Matrix Travels 最大费用最大流

    http://poj.org/problem?id=3422 /* 题意:给定一个n*n的矩形方格,要求从(1,1)出发,只能往右下角走,(i + 1,j) 或者 (i + n,j)每次走完将格子里面 ...

  6. poj3422 Kaka's Matrix Travels(最小费用最大流问题)

    1 /* 2 poj3422 Kaka's Matrix Travels 3 不知道 k次 dp做为什么不对??? 4 看了大牛的代码,才知道还可以这样做! 5 开始没有理解将a 和 a' 之间建立怎 ...

  7. Kaka's Matrix Travels(减弱版) DP版

    Kaka's Matrix Travels(减弱版) Time Limit:5000MS  Memory Limit:65536K Total Submit:15 Accepted:8 Descrip ...

  8. POJ3422 Kaka's Matrix Travels

    描述 On an N × N chessboard with a non-negative number in each grid, Kaka starts his matrix travels wi ...

  9. hdu Kaka's Matrix Travels(最小费用最大流)

    把题意写一下:  给你一个n*n的矩阵,每个格子都有一个非负整数,从左上角走到右下角,收集走过的数字,累加,但是只能向右或者向下走,走过之后数字就变为0,让你求从左上角到右下角,走k次之后,所得的最大 ...

最新文章

  1. 用python做毕业设计小程序_用Python写一个模拟qq聊天小程序的代码实例
  2. 在桌面建立快捷_用 ROX 桌面重温 Linux 历史 | Linux 中国
  3. java的解释程序_JAVA改错和程序解释
  4. 小米鸿蒙1001小米鸿蒙,小米高管早就放下狠话!愿意使用鸿蒙2.0系统:那其他厂商呢?...
  5. Vmware工作笔记-通过光驱位与虚拟机(Vmware)共享数据【含iso制作】
  6. thinkphp5 memcached 安装、调用、链接
  7. Go语言中命令行参数的实现
  8. Tomcat服务器解析“GET /JavaWebDemo1/1.jsp HTTP/1.1”
  9. 高德API地名转化为坐标
  10. 异步ajax动态实现级联,JQuery异步加载无限下拉框级联功能实现示例
  11. 如何实现远程给PLC上下载程序?
  12. 【转】Java线程池实现原理及其在美团业务中的实践
  13. input隐藏域传值
  14. 单片机移频防啸叫_JDS M-9108全自动高速移频反馈抑制器 会议鹅颈话筒麦克风防啸叫...
  15. 计算机内存和外存的主要区别是什么,计算机的存储系统一般有内存和外存,试述内存与外存的主要区别。...
  16. 【并发编程神器】,Worker Thread模式
  17. Linux内核踩坑笔记
  18. 前端基础教程:简单的实现html+css+javascript点赞效果
  19. xmanager linux 远程桌面,Windows系统下通过xmanager远程桌面控制Linux
  20. 苹果计算机如何出现关机界面,电脑关机.教您苹果电脑怎么关机

热门文章

  1. 老司机找bug的心路历程
  2. relative与absolute相结合
  3. DataGridView 编程
  4. Object Relational Tool Comparison Dot Net
  5. 微软提出第一个端到端的Video Captioning方法:SWIN BERT,涨点显著!
  6. 北大阿里中科院提出细粒度人体姿态迁移方法,提升外观细节逼真度
  7. DeOccNet:国防科大提出阵列相机去除前景遮挡成像新方法
  8. ChinaMM竞赛:低光照人脸检测
  9. 今日头条新出算法大赛!短视频内容理解与推荐竞赛
  10. 腾讯内容平台部-视频内容理解算法实习生