题意:一个三角形水域,每条边上住着n,m,k户人,他们要互相连通就得架桥,桥必须满足两个条件:1、互相不交叉。2、每一户人家都必须有至少一座桥。桥的代价为两户人家海拔高度之差,求此情况下的最优架桥方案代价。

题解:类似于一道经典DP,忘了是哪个了,可以将三角区域看成三角形,分别对三个角进行dp,方案如下:

   1、对于角A,它关联的两条边分住着x1,x2...xn和zk,zk-1....z1这些人家,那么dpa[i][j]代表xi户人与zj户人搭桥且所有<i的x与所有大于j的z均已成功搭建好桥的最小代价,B,C角类似处理。

   2、枚举dpa[i][j],即从A开始,最远的zj与xi之间建的桥,然后再枚举BC边上的t,从B开始,最远的yt与xi或者xi+1建桥,然后yt或yt+1与zj或zj-1建桥。取最小值。

View Code
 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 using namespace std;
 5 const int N=105,inf=0x1f1f1f1f;
 6 int dpa[N][N],dpb[N][N],dpc[N][N],x[N],y[N],z[N];
 7 int getmin(int i,int j,int t)
 8 {
 9     int ans=min(dpa[i][j]+dpb[i][t]+dpc[t][j],dpa[i][j]+dpb[i][t]+dpc[t][j-1]);
10     ans=min(ans,min(dpa[i][j]+dpb[i][t]+dpc[t+1][j],dpa[i][j]+dpb[i][t]+dpc[t+1][j-1]));
11     ans=min(ans,min(dpa[i][j]+dpb[i+1][t]+dpc[t+1][j],dpa[i][j]+dpb[i+1][t]+dpc[t+1][j-1]));
12     return min(ans,min(dpa[i][j]+dpb[i+1][t]+dpc[t][j],dpa[i][j]+dpb[i+1][t]+dpc[t][j-1]));
13 }
14 int main()
15 {
16     int T,n,m,k;
17     for(scanf("%d",&T);T;T--)
18     {
19         scanf("%d%d%d",&n,&m,&k);
20         for(int i=1;i<=n;i++)
21             scanf("%d",x+i);
22         for(int i=1;i<=m;i++)
23             scanf("%d",y+i);
24         for(int i=1;i<=k;i++)
25             scanf("%d",z+i);
26         memset(dpa,0x1f,sizeof(dpa));
27         memset(dpb,0x1f,sizeof(dpb));
28         memset(dpc,0x1f,sizeof(dpc));
29         dpa[0][k+1]=dpb[n+1][0]=dpc[m+1][0]=0;
30         for(int i=1;i<=n;i++)
31             for(int j=k;j>=1;j--)
32             {
33                 int tp=inf,cc=0;
34                 for(int t=j;t<=k;t++)
35                     cc+=abs(x[i]-z[t]),tp=min(tp,cc+min(dpa[i-1][t+1],dpa[i-1][t]));
36                 dpa[i][j]=tp;
37             }
38         for(int i=n;i>=1;i--)
39             for(int j=1;j<=m;j++)
40             {
41                 int tp=inf,cc=0;
42                 for(int t=j;t>=1;t--)
43                     cc+=abs(x[i]-y[t]),tp=min(tp,cc+min(dpb[i+1][t],dpb[i+1][t-1]));
44                 dpb[i][j]=tp;
45             }
46         for(int i=m;i>=1;i--)
47             for(int j=1;j<=k;j++)
48             {
49                 int tp=inf,cc=0;
50                 for(int t=j;t>=1;t--)
51                     cc+=abs(y[i]-z[t]),tp=min(tp,cc+min(dpc[i+1][t],dpc[i+1][t-1]));
52                 dpc[i][j]=tp;
53             }
54         int ans=inf;
55         for(int i=0;i<=n+1;i++)
56             for(int j=k+1;j>=0;j--)
57                 for(int t=0;t<=m+1;t++)
58                     ans=min(ans,getmin(i,j,t));
59         printf("%d\n",ans);
60     }
61     return 0;
62 }