河南省第六届acm省赛 探寻宝藏&& poj 3422 (最大费用最大流)
来源:互联网 发布:黑蚂蚁网络电视 编辑:程序博客网 时间:2024/06/05 02:36
题目描述
传说HMH大沙漠中有一个M*N迷宫,里面藏有许多宝物。某天,Dr.Kong找到了迷宫的地图,他发现迷宫内处处有宝物,最珍贵的宝物就藏在右下角,迷宫的进出口在左上角。当然,迷宫中的通路不是平坦的,到处都是陷阱。Dr.Kong决定让他的机器人卡多去探险。
但机器人卡多从左上角走到右下角时,只会向下走或者向右走。从右下角往回走到左上角时,只会向上走或者向左走,而且卡多不走回头路。(即:一个点最多经过一次)。当然卡多顺手也拿走沿路的每个宝物。
Dr.Kong希望他的机器人卡多尽量多地带出宝物。请你编写程序,帮助Dr.Kong计算一下,卡多最多能带出多少宝物。
输入
第一行: K 表示有多少组测试数据。
接下来对每组测试数据:
第1行: M N
第2~M+1行: Ai1 Ai2 ……AiN (i=1,…..,m)
2≤k≤5 1≤M, N≤50 0≤Aij≤100 (i=1,….,M; j=1,…,N)
所有数据都是整数。 数据之间有一个空格。
输出
对于每组测试数据,输出一行:机器人卡多携带出最多价值的宝物数
样例输入
22 30 10 1010 10 803 30 3 92 8 55 7 100
样例输出
120134
题意:左上走到右下捡数字,走两次,求最大和
求最大费用最大流只需把费用变成负数,用spfa找到一条费用最大的路
还有就是要拆点建图,一个点拆成两个,其中一条边费用为对应数字,流量1,另一条边费用为0,流量1
然后设个超级源点和超级汇点,分别连接左上,右下
这个和poj3422有些类似,那个题是走k次,这个只走两次
拆点建图,建完的图,就是每个点拆为两个,1&1',s→1→→1’→2→→2' 然后1↓3→→3'→4→→4’
大概就这个意思,上下左右也要连起来
代码注释:
#include<iostream>#include<cstring>#include<algorithm>#include<queue>using namespace std;#define N 5050#define inf 0x7fffffffint n,m,s,t,maxflow,o;struct node{ int u,v,c,f,next;} a[100000];int visit[N];int pre[N];int head[N];int dis[N];int map[55][55];void add(int u,int v,int c,int f) //c为费用,f流量{ a[o].u=u,a[o].v=v,a[o].c=c,a[o].f=f; a[o].next=head[u],head[u]=o++; a[o].u=v,a[o].v=u,a[o].c=-c,a[o].f=0;//建立反边 a[o].next=head[v],head[v]=o++;}int spfa(){ int i,u,v; memset(visit,0,sizeof(visit)); memset(pre,-1,sizeof(pre)); for(i=0; i<=t; i++) dis[i]=inf; queue<int>q; while(!q.empty()) q.pop(); q.push(s); visit[s]=1; dis[s]=0; while(!q.empty()) { u=q.front(); q.pop(); for(i=head[u]; i!=-1; i=a[i].next) { v=a[i].v; if(a[i].f>0&&dis[u]+a[i].c<dis[v]) { dis[v]=dis[u]+a[i].c; pre[v]=i; if(!visit[v]) { visit[v]=1; q.push(v); } } } visit[u]=0; } if(dis[t]==inf) return 0; return 1;}void Add()//修改残留网络{ int i; int mm=inf; for(i=pre[t]; a[i].u!=s; i=pre[a[i].u])//找到最小可增流 mm=min(mm,a[i].f); for(i=pre[t]; a[i].u!=s; i=pre[a[i].u]) { a[i].f-=mm; a[i^1].f+=mm;//修改 maxflow+=mm*a[i].c;//加到maxflow中 }}int main(){ int T,i,j,x; cin>>T; while(T--) { cin>>n>>m; o=0; maxflow=0; memset(head,-1,sizeof(head)); for(i=1; i<=n; i++) for(j=1; j<=m; j++) cin>>map[i][j]; for(i=1; i<=n; i++) for(j=1; j<=m; j++) { x=(i-1)*m+j-1; add(2*x,2*x+1,-map[i][j],1);//拆点构图,费用置为负 add(2*x,2*x+1,0,1); } for(i=1; i<=n; i++) for(j=1; j<m; j++)//向右边建图 { x=(i-1)*m+j-1; add(2*x+1,2*(x+1),0,2); } for(i=1; i<n; i++) for(j=1; j<=m; j++)//向下边建图 { x=(i-1)*m+j-1; add(x*2+1,2*(x+m),0,2); } s=n*m*2; t=n*m*2+1; add(s,0,0,2); add(n*m*2-1,t,0,2);//连接源点汇点 while(spfa()) Add(); cout<<-maxflow<<endl; }}
这里再贴出poj 3422 题目连接:点击打开链接
题意上面说过了
代码:
#include<iostream>//和上面那题对比,这个是个n*n的 建图时好建,然后拆点,一条边流量为1,另一条为k-1#include<cstring>#include<queue>using namespace std;#define M 5050#define N 100000#define inf 0x7ffffffstruct node{ int u,v,c,f,next;} a[N];int head[M];int visit[M];int pre[M];int dis[M];int s,t,maxflow,num,k,n;void add(int u,int v,int c,int f){ a[num].u=u; a[num].v=v; a[num].f=f; a[num].c=c; a[num].next=head[u]; head[u]=num++; a[num].u=v; a[num].v=u; a[num].f=0; a[num].c=-c; a[num].next=head[v]; head[v]=num++;}int spfa(){ memset(pre,-1,sizeof(pre)); memset(visit,0,sizeof(visit)); for(int i=0; i<=t; i++) dis[i]=inf; dis[s]=0; queue<int>q; visit[s]=1; q.push(s); while(!q.empty()) { int u=q.front(); q.pop(); for(int i=head[u]; i!=-1; i=a[i].next) { int v=a[i].v; if(a[i].f>0&&dis[u]+a[i].c<dis[v]) { dis[v]=dis[u]+a[i].c; pre[v]=i; if(!visit[v]) { visit[v]=1; q.push(v); } } } visit[u]=0; } if(dis[t]==inf) return 0; return 1;}void Add(){ int v; int mm=inf; for(v=pre[t]; a[v].u!=s; v=pre[a[v].u]) mm=min(mm,a[v].f); for(v=pre[t]; a[v].u!=s; v=pre[a[v].u]) { a[v].f-=mm; a[v^1].f+=mm; maxflow+=mm*a[v].c; }}int map[100][100];int main(){ while(cin>>n>>k) { maxflow=0; s=n*n*2; t=s+1; num=0; memset(head,-1,sizeof(head)); for(int i=1; i<=n; i++) for(int j=1; j<=n; j++) cin>>map[i][j]; for(int i=1; i<=n; i++) for(int j=1; j<=n; j++) { int b=(i-1)*n+j-1; add(b*2,2*b+1,-map[i][j],1); add(b*2,b*2+1,0,k-1); } for(int i=1; i<=n; i++) for(int j=1; j<n; j++) { int b=(i-1)*n+j-1; add(2*b+1,2*(b+1),0,k); } for(int i=1; i<n; i++) for(int j=1; j<=n; j++) { int b=(i-1)*n+j-1; add(b*2+1,2*(b+n),0,k); } add(s,0,0,k); add(n*n*2-1,t,0,k); while(spfa()) Add(); cout<<-maxflow<<endl; }}
0 0
- 河南省第六届acm省赛 探寻宝藏&& poj 3422 (最大费用最大流)
- 河南省第六届省赛 探寻宝藏 dp
- poj 3422(最大费用最大流)
- 最大费用最大流模版(POJ 3422)
- 第八届河南省ACM省赛 - B - 最大岛屿
- 第六届省赛题 探寻宝藏
- poj 3422(最小费用最大流)
- POJ 3422 最小费用最大流
- POJ-3422-最大流最小费用
- poj 2159(最小费用最大流)
- POJ 2516(最小费用最大流)
- poj 2195 (最小费用最大流)
- poj 2516(最小费用最大流)
- POJ 3422 Kaka's Matrix Travels (最大费用最大流)
- POJ 3422 Kaka's Matrix Travels (最大费用最大流)
- 【最大费用最大流】POJ-3422 Kaka's Matrix Travels
- POJ 3422 Kaka's Matrix Travels 最大费用最大流
- POJ Kaka's Matrix Travels (最大费用最大流)
- Android OpenGL ES 开发教程(7):创建实例应用OpenGLDemos程序框架
- JVM加载class文件的原理
- Oracle 绑定变量 详解
- Chrome 被和谐的解决办法
- VC中MessageBox的常见用法
- 河南省第六届acm省赛 探寻宝藏&& poj 3422 (最大费用最大流)
- PIC单片机红外遥控编码及识别.
- html添加的锚点
- acdream群赛(4)Bad Horse(种类并查集)
- LeetCode-Subsets
- C 语言计算精确时间
- C++第十九天 面向对象编程
- 如何让开饭板跑出图来
- LBaas 原理分析