思路:
dp方法:
设dp[i][j][k][l]为两条没有交叉的路径分别走到(i,j)和(k,l)处最大价值。
则转移方程为
dp[i][j][k][l]=max(dp[i-1][j][k-1][l],dp[i][j-1][k-1][l],dp[i-1][j][k][l-1],dp[i][j-1][k][l-1])+map[i][j]+map[k][l];
若两点相同减去一个map[i][j]即可
费用流方法(可以扩展为k条路径,但时间复杂度较高):
源点连接左上角点流量为k、费用为0,右下角点连接汇点流量为k、费用为0,所有点连接右边相邻和下边相邻点流量为k、费用为0,所有点拆点一条流量为1、费用为该
点价值,一条流量为k-1、费用为0。跑最大费用流即可
代码:
dp:
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <iostream> 5 #include <vector> 6 #include <queue> 7 #include <cmath> 8 #include <set> 9 using namespace std; 10 11 #define N 55 12 13 __int64 map[N][N]; 14 __int64 dp[N][N][N][N]; 15 int n, m; 16 17 main() 18 { 19 int i, j, k, l; 20 int x, y, w; 21 while(scanf("%d %d",&n,&m)==2){ 22 memset(map,0,sizeof(map)); 23 memset(dp,0,sizeof(dp)); 24 for(i=1;i<=n;i++){ 25 for(j=1;j<=m;j++){ 26 scanf("%I64d",&map[i][j]); 27 } 28 } 29 for(i=1;i<=n;i++){ 30 for(j=1;j<=m;j++){ 31 for(k=1;k<=n;k++){ 32 for(l=1;l<=m;l++){ 33 dp[i][j][k][l]=max(dp[i][j][k][l],dp[i-1][j][k-1][l]); 34 dp[i][j][k][l]=max(dp[i][j][k][l],dp[i][j-1][k-1][l]); 35 dp[i][j][k][l]=max(dp[i][j][k][l],dp[i-1][j][k][l-1]); 36 dp[i][j][k][l]=max(dp[i][j][k][l],dp[i][j-1][k][l-1]); 37 dp[i][j][k][l]+=map[i][j]+map[k][l]; 38 if(i==k&&j==l) dp[i][j][k][l]-=map[i][j]; 39 } 40 } 41 } 42 } 43 printf("%I64d ",dp[n][m][n][m]); 44 } 45 }
费用流:
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <iostream> 5 #include <vector> 6 #include <queue> 7 #include <cmath> 8 #include <set> 9 using namespace std; 10 11 #define N 205 12 #define M 1005 13 #define inf 999999999 14 15 struct MCF{//min_cost_flow 16 struct Edge{ 17 int v, f, w, next; 18 Edge(){}; 19 Edge(int a,int b,int c,int d){ 20 v=a;f=b;w=c;next=d; 21 } 22 }; 23 int n; 24 int head[N+10]; 25 Edge e[M*2]; 26 int nume; 27 int src, sink; 28 29 void init(int st, int end,int nn){//初始化 30 src=st;sink=end;n=nn; 31 memset(head,0,sizeof(head)); 32 nume=1; 33 } 34 35 void addedge(int u,int v,int c,int w){ 36 e[++nume]=Edge(v,c,w,head[u]); 37 head[u]=nume; 38 e[++nume]=Edge(u,0,-w,head[v]); 39 head[v]=nume; 40 } 41 42 43 queue<int>Q; 44 bool visited[N]; 45 int dis[N]; 46 int prev[N], pree[N]; 47 48 bool findpath(){ 49 50 while(!Q.empty()) Q.pop(); 51 Q.push(src); 52 for(int i=0;i<=n;i++) dis[i]=-1; 53 dis[src]=0; 54 visited[src]=true; 55 while(!Q.empty()){ 56 int u=Q.front();Q.pop();visited[u]=false; 57 for(int i=head[u];i;i=e[i].next){ 58 if(e[i].f>0&&dis[u]+e[i].w>dis[e[i].v]){ 59 dis[e[i].v]=dis[u]+e[i].w; 60 prev[e[i].v]=u; 61 pree[e[i].v]=i; 62 if(!visited[e[i].v]){ 63 Q.push(e[i].v); 64 visited[e[i].v]=true; 65 } 66 } 67 } 68 }//printf("111111 "); 69 if(dis[sink]>0) return true; 70 else return false; 71 } 72 73 int solve(){ 74 75 int u=sink; 76 int flow=inf; 77 while(u!=src){ 78 if(e[pree[u]].f<flow) flow=e[pree[u]].f; 79 u=prev[u]; 80 } 81 u=sink; 82 while(u!=src){ 83 e[pree[u]].f-=flow; 84 e[pree[u]^1].f+=flow; 85 u=prev[u]; 86 } 87 88 return dis[sink]*flow; 89 } 90 91 int mincostflow(){ 92 int ans=0; 93 while(findpath()){ 94 ans+=solve(); 95 } 96 return ans; 97 } 98 }mcf; 99 100 int n; 101 int map[10][10]; 102 103 int x, y, w; 104 105 main() 106 { 107 int i, j, k; 108 while(scanf("%d",&n)==1){ 109 memset(map,0,sizeof(map)); 110 while(1){ 111 112 scanf("%d %d %d",&x,&y,&w); 113 if(x==0&&y==0&&w==0) break; 114 map[x][y]=w; 115 } 116 mcf.init(0,n*n*2+1,n*n*2+2); 117 mcf.addedge(0,1,2,0); 118 mcf.addedge(n*n*2,n*n*2+1,2,0); 119 int temp=1; 120 for(i=1;i<=n;i++){ 121 for(j=1;j<=n;j++){ 122 mcf.addedge(temp,temp+n*n,1,map[i][j]); 123 mcf.addedge(temp,temp+n*n,1,0); 124 if(i<n) mcf.addedge(temp+n*n,temp+n,2,0); 125 if(j<n) mcf.addedge(temp+n*n,temp+1,2,0); 126 temp++; 127 } 128 } 129 printf("%d ",mcf.mincostflow()); 130 } 131 }