题意:n(<=100)头牛各自有s(<=40)个自己喜欢的地方,FJ要把它们用绳子连成一个圈,但是每头牛都要在自己喜欢的地方之一才行,问FJ最少要用多长的绳子才行。

题解:有于数据都比较小,所以可以dp[i][j][k]代表第i头牛在j处吃草时第1头牛在k处的最小绳子,最后答案等于dp[n][i][j]+dist(0,j,n,i)的最小值。转移是s的复杂度,最后就是O(n*s^3)

View Code
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<cmath>
 5 using namespace std;
 6 double dp[102][42][42];
 7 struct _cow
 8 {
 9     int num;
10     double x[42],y[42];
11 } cow[102];
12 inline double getdist(int i,int ii,int j,int jj)
13 {
14     double x1=cow[i].x[ii],y1=cow[i].y[ii];
15     double x2=cow[j].x[jj],y2=cow[j].y[jj];
16     return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
17 }
18 int main()
19 {
20     int n;
21     while(scanf("%d",&n)!=EOF)
22     {
23         for(int i=1; i<=n; i++)
24         {
25             int num;
26             scanf("%d",&num);
27             cow[i].num=num;
28             for(int j=0; j<num; j++)
29                 scanf("%lf%lf",&cow[i].x[j],&cow[i].y[j]);
30         }
31         int cnt=cow[1].num,cc=cow[2].num;
32         for(int i=0; i<cc; i++)
33             for(int j=0; j<cnt; j++)
34                 dp[2][i][j]=getdist(1,j,2,i);
35         for(int i=3; i<=n; i++)
36         {
37             int ln=cow[i-1].num,nn=cow[i].num;
38             for(int j=0; j<nn; j++)
39             {
40                 for(int k=0; k<cnt; k++)
41                 {
42                     dp[i][j][k]=1e50;
43                     for(int t=0; t<ln; t++)
44                     {
45                         dp[i][j][k]=min(dp[i][j][k],dp[i-1][t][k]+getdist(i-1,t,i,j));
46                     }
47                 }
48             }
49         }
50         double ans=1e50;
51         int num=cow[n].num;
52         for(int i=0; i<cnt; i++)
53         {
54             for(int j=0; j<num; j++)
55                 ans=min(ans,dp[n][j][i]+getdist(n,j,1,i));
56         }
57         printf("%d\n",(int)floor(ans*100.0));
58     }
59     return 0;
60 }