标签:des style blog class code c
Time Limit: 2000/1000 MS
(Java/Others) Memory Limit: 32768/32768 K
(Java/Others)
Total Submission(s): 1394 Accepted
Submission(s): 758
最大费用最大流,搞了好久= =!
题意:
给出一个n*n的矩阵,求(1,1)到(n,n)的两条不想交不重叠的路径,使经过的点的和最大。
开始想到的是DP,后来发现了可以用多线程DP实现:
参考:http://www.cnblogs.com/jackge/archive/2013/04/17/3025628.html
让两个进程同时进行,枚举步数K,当x1==x2||y1==y2时跳过,得状态转移方程:
dp(k, x1, y1, x2, y2) = max(dp(k-1, x1-1, y1, x2-1, y2), dp(k-1, x1-1, y1, x2, y2-1), dp(k-1, x1, y1-1, x2-1, y2), dp(k-1, x1, y1-1,x2, y2-1))
+ data(x1, y1) + data(x2, y2) ;
由于只能走右或下,所以坐标满足x+y=k。这样就能降低维数为3维,方程:
dp(k, x1, x2) = max(dp(k-1, x1, x2), dp(k-1, x1-1, x2), dp(k-1, x1, x2-1), dp(k-1, x1-1, x2-1)) + data(x1, k-x1) + data(x2, k-x2) ;
code:
1 //31MS 1196K 880 B G++ 2 #include<stdio.h> 3 #include<string.h> 4 #define N 50 5 int p[N][N]; 6 int dp[2*N][N][N]; 7 int max(int a,int b) 8 { 9 return a>b?a:b; 10 } 11 int Max(int a,int b,int c,int d) 12 { 13 return max(a,max(b,max(c,d))); 14 } 15 int main(void) 16 { 17 int n; 18 while(scanf("%d",&n)!=EOF) 19 { 20 memset(dp,0,sizeof(dp)); 21 for(int i=0;i<n;i++) 22 for(int j=0;j<n;j++) 23 scanf("%d",&p[i][j]); 24 for(int k=1;k<2*n-2;k++) 25 for(int i=0;i<n;i++) 26 for(int j=0;j<n;j++){ 27 if(i==j) continue; 28 dp[k][i][j]=Max(dp[k-1][i][j],dp[k-1][i-1][j],dp[k-1][i][j-1],dp[k-1][i-1][j-1]); 29 dp[k][i][j]+=p[i][k-i]+p[j][k-j]; 30 } 31 int ans=max(dp[2*n-3][n-1][n-2],dp[2*n-3][n-2][n-1])+p[0][0]+p[n-1][n-1]; 32 printf("%d\n",ans); 33 } 34 return 0; 35 }
先拆点构图,每个点一分为二,保证了只经过一次,其实网络流的方法就已经解决了这个问题,其次构图时注意把数变为负数,求最小费用最大流。
其实构好图后就是直接套模板了,所以构图的时候注意点,处理一下(1,1)和(n,n)两个点,因为会经过两次。
code:
1 //31MS 384K 2396 B G++ 2 #include<stdio.h> 3 #include<string.h> 4 #include<queue> 5 #define N 2005 6 #define inf 0x7ffffff 7 using namespace std; 8 struct node{ 9 int u,v,c,w; 10 int next; 11 }edge[10*N]; 12 int vis[N]; 13 int Head[N],d[N],edgenum; 14 int pre[N],path[N]; 15 void addedge(int u,int v,int c,int w) 16 { 17 edge[edgenum].u=u; 18 edge[edgenum].v=v; 19 edge[edgenum].c=c; 20 edge[edgenum].w=w; 21 edge[edgenum].next=Head[u]; 22 Head[u]=edgenum++; 23 24 edge[edgenum].u=v; 25 edge[edgenum].v=u; 26 edge[edgenum].c=0; 27 edge[edgenum].w=-w; 28 edge[edgenum].next=Head[v]; 29 Head[v]=edgenum++; 30 } 31 int SPFA(int s,int e) 32 { 33 memset(vis,0,sizeof(vis)); 34 memset(pre,-1,sizeof(pre)); 35 for(int i=0;i<=e;i++) 36 d[i]=inf; 37 queue<int>Q; 38 d[s]=0; 39 vis[s]=1; 40 Q.push(s); 41 while(!Q.empty()){ 42 int u=Q.front(); 43 Q.pop(); 44 vis[u]=0; //这里WA了好多次 45 for(int i=Head[u];i!=-1;i=edge[i].next){ 46 int v=edge[i].v; 47 int w=edge[i].w; 48 if(edge[i].c>0 && d[v]>d[u]+w){ 49 pre[v]=u; 50 path[v]=i; 51 d[v]=d[u]+w; 52 if(!vis[v]){ 53 vis[v]=1; 54 Q.push(v); 55 } 56 } 57 } 58 } 59 if(pre[e]!=-1) return 1; 60 return 0; 61 } 62 int cost_min_flow(int s,int e) 63 { 64 int cost=0; 65 while(SPFA(s,e)){ 66 int minc=inf; 67 for(int i=e;i!=s;i=pre[i]){ 68 minc=minc<edge[path[i]].c?minc:edge[path[i]].c; 69 } 70 for(int i=e;i!=s;i=pre[i]){ 71 edge[path[i]].c-=minc; 72 edge[path[i]^1].c+=minc; 73 cost+=minc*edge[path[i]].w; 74 } 75 } 76 return cost; 77 } 78 int main(void) 79 { 80 int n; 81 int p[50][50]; 82 while(scanf("%d",&n)!=EOF) 83 { 84 edgenum=0; 85 memset(Head,-1,sizeof(Head)); 86 int k=n*n; 87 int s=0,e=2*k+1; 88 for(int i=1;i<=n;i++) 89 for(int j=1;j<=n;j++){ 90 scanf("%d",&p[i][j]); 91 addedge(j+(i-1)*n,k+j+(i-1)*n,1,-p[i][j]); 92 if(j!=n) addedge(k+j+(i-1)*n,j+1+(i-1)*n,1,0); 93 if(i!=n) addedge(k+j+(i-1)*n,j+i*n,1,0); 94 } 95 addedge(s,1,2,0); 96 addedge(1,k+1,1,0); 97 addedge(2*k,e,2,0); 98 addedge(k,2*k,1,0); 99 printf("%d\n",-cost_min_flow(s,e)); 100 } 101 return 0; 102 }
hdu 2686 Matrix && hdu 3367 Matrix Again (最大费用最大流),布布扣,bubuko.com
hdu 2686 Matrix && hdu 3367 Matrix Again (最大费用最大流)
标签:des style blog class code c
原文地址:http://www.cnblogs.com/GO-NO-1/p/3726322.html