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 }
没有人能阻止我前进的步伐,除了我自己!
原文地址:https://www.cnblogs.com/proverbs/p/2711151.html