★ HDU 4862 带费用的最小K路径覆盖
来源:互联网 发布:激战2画面优化设置 编辑:程序博客网 时间:2024/05/09 23:30
题意:给你一个n*m的网格,每个网格里有一个整数,每次你可以选择任意一个点为起点开始跳,每次只能向右或者向下跳,长度任意,跳过的格子不能再跳,问你在K次之内是否能够恰好经过所有格子仅一次。
分析:带费用的最小K路径覆盖模型。这题关键在于K次限制的处理,的确很巧妙啊。我们将图建成二分图,将网格中每个点拆成两个点,X部正好n*m个点,Y部也正好n*m个点,设立源汇点S,T,先从S点出发,X部中的每个点建边add(x,y,1,0),然后Y部每个点向T建边,add(i+n*m,T,1,0),接下来就是比较巧妙的地方,在X部中加入一个点Q,从S点向Q建边add(S,Q,k,0)(容量为k,费用为0),然后Q点向Y部中每个点建边add(Q,i+n*m,1,0),最后对于网格中的每个点走向关系,在X部和Y部之间建边,边的权值为(两点之间的曼哈顿距离-1-可以得到的能量),最后跑最小费用最大流即可。感叹K次限制的建边处理。
代码:
//O(Kn^2m)//如果要求最大费用的话 只需在加边的时候加-的边 输出时输出-ans即可#pragma comment(linker,"/STACK:102400000,102400000")#include <iostream>#include <string.h>#include <stdio.h>#include <algorithm>#include <vector>#include <string>#include <math.h>#include <queue>#include <stack>#include <map>#include <set>using namespace std;typedef long long ll; //记得必要的时候改成无符号const int maxn=250;const int maxm=1000005;const int INF=1000000000;struct EdgeNode{ int from; int to; int flow; int cost; int next;}edge[maxm];int head[maxn],cnt;int pre[maxn],d[maxn];bool vis[maxn];queue<int>Q;int S,T,n,m,k,K;void init(){ cnt=0; memset(head,-1,sizeof(head));}void add(int x,int y,int z,int c){ edge[cnt].from=x; edge[cnt].to=y; edge[cnt].flow=z; edge[cnt].cost=c; edge[cnt].next=head[x]; head[x]=cnt++; edge[cnt].from=y; edge[cnt].to=x; edge[cnt].flow=0; edge[cnt].cost=-c; edge[cnt].next=head[y]; head[y]=cnt++;}bool spfa(int S,int T){ while(!Q.empty())Q.pop(); memset(vis,false,sizeof(vis)); memset(pre,-1,sizeof(pre)); for(int i=0;i<n+5;i++)d[i]=INF; d[S]=0; vis[S]=true; Q.push(S); while(!Q.empty()) { int u=Q.front(); Q.pop(); vis[u]=false; for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].to; if(edge[i].flow&&d[v]>d[u]+edge[i].cost) { d[v]=d[u]+edge[i].cost; pre[v]=i; if(!vis[v]) { vis[v]=true; Q.push(v); } } } } if(pre[T]==-1)return false; else return true;}int MCMF(int S,int T){ int maxflow=0; int mincost=0; while(spfa(S,T)) { int Min=INF; for(int i=pre[T];i!=-1;i=pre[edge[i^1].to]) { if(Min>edge[i].flow) Min=edge[i].flow; } for(int i=pre[T];i!=-1;i=pre[edge[i^1].to]) { edge[i].flow-=Min; edge[i^1].flow+=Min; mincost+=edge[i].cost*Min; } maxflow+=Min; } if(maxflow!=K)printf("-1\n"); else printf("%d\n",-mincost);}int main(){ int t,i,j,x,y,z,l; char s[15][15]; scanf("%d",&t); for(l=1;l<=t;l++){ scanf("%d%d%d",&n,&m,&k); init(); K=n*m; S=0; T=2*K+2; add(S,T-1,k,0); for(i=1;i<=n;i++)scanf("%s",s[i]+1); for(i=1;i<=K;i++){ add(S,i,1,0); add(T-1,i+K,1,0); add(i+K,T,1,0); } for(i=1;i<=n;i++){ for(j=1;j<=m;j++){ x=(i-1)*m+j; for(k=j+1;k<=m;k++){ y=(i-1)*m+k+K; z=k-j-1; if(s[i][j]==s[i][k])z-=s[i][j]-'0'; add(x,y,1,z); } for(k=i+1;k<=n;k++){ y=(k-1)*m+j+K; z=k-i-1; if(s[i][j]==s[k][j])z-=s[i][j]-'0'; add(x,y,1,z); } } } n=T+2; printf("Case %d : ",l); MCMF(S,T); } return 0;}
0 0
- ★ HDU 4862 带费用的最小K路径覆盖
- HDU 4862 Jump 最小k路径覆盖 费用流
- hdu 4862 最小k路径覆盖 费用流
- hdu 4862 Jump(最小k路径覆盖)
- hdu 4862 KM算法 最小K路径覆盖的模型
- 网络费用流-最小k路径覆盖
- HDU 4862 最小费用最大流+路径覆盖
- HDU 4862 Jump (最小K路径覆盖)
- 2014杭电多校联合第一场Jump费用流(最小K路径覆盖)
- HDU 4106 Fruit Ninja 区间k覆盖问题 最小费用流
- HDU 3488 最小费用圈覆盖
- 【最小路径覆盖】HDU 4160
- hdu 1151 最小路径覆盖
- hdu 1151 最小路径覆盖
- HDU - 4160 最小路径覆盖
- hdu Matrix(二分图的最小路径覆盖)
- HDU 1151 Air Raid 二分图的最小路径覆盖
- hdu 1151 Air Raid DaG 图的最小路径覆盖
- busybo命令帮助信息
- 黑马高新技术 枚举篇
- lightoj 1008
- 测试CPU支持指令集AVX,AVX2,SSE情况的代码【VS2010调试通过】
- Git 环境搭建
- ★ HDU 4862 带费用的最小K路径覆盖
- HDU 1070 Milk
- MySQL执行计划不准确 -概述
- C++ 使用oci访问数据库出现“Column: 2<DOUBLE>, datatype in operator <</>>: CHAR”
- ORACLE常用数据类型
- 使用 __attribute__ ((packed))让结构体编译时内存不对齐
- 虚指针(虚函数表)
- 8.6_java学习_文件随机存取
- 成为优秀程序员的十个有效方法