POJ 1682 多重DP
题意:
有三个相互隔离的河岸X,Y,Z,每个岸上分别有n,m,p个部落,每个河岸上的部落之间是敌对的(即同一个河岸上的部落之间不能连通),然而,位于不同河岸上的任意两个部落之间都是友好的,现在请你在部落之间搭建桥梁(不能交叉),每座桥的费用是两部落的海拔差的绝对值,求:使得每一个部落都能与至少一个他的友好部落连通 的桥的总费用。
友情提示:注意坐标的顺序
PS:自己连蒙带猜的题意,AC了。。O(∩_∩)O~
思路:
对于三个河岸,两两做一遍n^2的dp,再把三个dp结合起来做一遍dp(其实就是找最值)
河岸分布图:
x河岸从左向右部落编号是增大的,y、z河岸自己看吧~
借用了LYD神犇的一张图片嘿嘿~
xz[i][j]表示河岸x的i与河岸z的j之间要修一座桥,且满足x河岸的i~n和z河岸的1~j与对岸连通
xy[i][j]表示河岸x的i与河岸y的j之间要修一座桥,且满足x河岸的i~n和y河岸的1~j与对岸连通
yz[i][j]表示河岸y的i与河岸z的j之间要修一座桥,且满足y河岸的i~n和z河岸的1~j与对岸连通
按照上边那样做三遍dp就完成了这道题目的第一步
接下来,就是将这三个数组整合在一起得到我们需要的答案了!
首先我们要思考整合的方式:(先告诉你4种类型共有8种情况,先自己想想再往下看)
以下图片黑线代表一条河岸,黑线与红线的交点是一个部落
第一种(封闭式,共一种):
第二种(一头开口式,共三种):
第三种(两头开口式,共三种):
第四种(开放式,共一种):
如果你还是看不懂的话,只能说明我的表达能力有问题。。。
上代码了~
View Code
1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <iostream> 5 #include <cmath> 6 7 #define N 150 8 9 using namespace std; 10 11 int n,m,p,a[N],b[N],c[N],xz[N][N],xy[N][N],yz[N][N],ans,tt; 12 13 void read() 14 { 15 scanf("%d%d%d",&m,&n,&p); 16 for(int i=1;i<=n;i++) scanf("%d",&a[i]); 17 for(int i=1;i<=m;i++) scanf("%d",&b[i]); 18 for(int i=1;i<=p;i++) scanf("%d",&c[i]); 19 for(int i=0;i<N;i++) 20 for(int j=0;j<N;j++) 21 xz[i][j]=xy[i][j]=yz[i][j]=999999; 22 ans=999999; 23 } 24 25 void go() 26 { 27 xz[0][p+1]=0; 28 for(int i=1;i<=n;i++) 29 for(int j=p;j>=1;j--) 30 xz[i][j]=min(min(xz[i-1][j+1],xz[i-1][j]),xz[i][j+1])+abs(a[i]-c[j]); 31 xy[n+1][0]=0; 32 for(int i=n;i>=1;i--) 33 for(int j=1;j<=m;j++) 34 xy[i][j]=min(min(xy[i+1][j-1],xy[i+1][j]),xy[i][j-1])+abs(a[i]-b[j]); 35 yz[m+1][0]=0; 36 for(int i=m;i>=1;i--) 37 for(int j=1;j<=p;j++) 38 yz[i][j]=min(min(yz[i+1][j-1],yz[i+1][j]),yz[i][j-1])+abs(b[i]-c[j]); 39 for(int i=0;i<=n+1;i++) 40 for(int j=0;j<=m+1;j++) 41 for(int k=0;k<=p+1;k++) 42 { 43 ans=min(ans,xy[i][j]+xz[i][k]+yz[j][k]); 44 45 ans=min(ans,xy[i][j]+xz[i][k]+yz[j+1][k]); 46 ans=min(ans,xy[i+1][j]+xz[i][k]+yz[j][k]); 47 ans=min(ans,xy[i][j]+xz[i][k+1]+yz[j][k]); 48 49 ans=min(ans,xy[i+1][j]+xz[i][k]+yz[j+1][k]); 50 ans=min(ans,xy[i][j]+xz[i][k+1]+yz[j+1][k]); 51 ans=min(ans,xy[i+1][j]+xz[i][k+1]+yz[j][k]); 52 53 ans=min(ans,xy[i+1][j]+xz[i][k+1]+yz[j+1][k]); 54 } 55 printf("%d\n",ans); 56 } 57 58 int main() 59 { 60 scanf("%d",&tt); 61 while(tt--) 62 { 63 read(); 64 go(); 65 } 66 system("pause"); 67 return 0; 68 }
没有人能阻止我前进的步伐,除了我自己!