首页 > 代码库 > 【四边形不等式】POJ1160[IOI2000]-Post Office

【四边形不等式】POJ1160[IOI2000]-Post Office

【题目大意】

v个村庄p个邮局,邮局在村庄里,给出村庄的位置,求每个村庄到最近邮局距离之和的最小值。

【思路】

四边形不等式,虽然我并不会证明:(

dp[i][j]表示前i个村庄建j个邮局的最小值,w[i][j]表示在i到j之间建立一个邮局的最小值。w[i][j]显然取i~j的中位数,可以在O(1)时间内求出。

显然dp[i][j]=min{dp[k][j-1]+w[k+1][i]}。

傻傻写错i和j……

 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 using namespace std; 7 const int MAXV=305; 8 const int MAXP=35; 9 const int INF=0x7fffffff;10 int v,p;11 int dis[MAXV],sum[MAXV],w[MAXV][MAXV];//w[i][j]表示在[i,j]间建立一个邮局的最小代价 12 int s[MAXV][MAXP],dp[MAXV][MAXP];13 14 void init()15 {16     scanf("%d%d",&v,&p);17     sum[0]=0;18     for (int i=1;i<=v;i++) scanf("%d",&dis[i]);19     sort(dis+1,dis+v+1);20     for (int i=1;i<=v;i++) sum[i]=dis[i]+sum[i-1];21     for (int i=1;i<=v;i++)22     {23         w[i][i]=0;24         for (int j=i+1;j<=v;j++)25         {26             if ((i+j)%2==0) w[i][j]=sum[j]-sum[(i+j)/2]-sum[(i+j)/2-1]+sum[i-1];27                 else w[i][j]=sum[j]-sum[(i+j)/2]-sum[(i+j)/2-1]+sum[i-1]-dis[(i+j)/2];28         }29     }30 }31 32 void solve()33 {34     memset(dp,127,sizeof(dp));35     for (int i=1;i<=v;i++) dp[i][1]=w[1][i];36     for (int j=2;j<=p;j++)37     {38         s[v+1][j]=v-1;39         for (int i=v;i>=j;i--)40         {41             for (int k=s[i][j-1];k<=s[i+1][j];k++)42             {43                 if (dp[i][j]>dp[k][j-1]+w[k+1][i])//一开始这里敲成了w[k+1][j] 44                 {45                     dp[i][j]=dp[k][j-1]+w[k+1][i];46                     s[i][j]=k;47                 }48             }49         } 50     }51     printf("%d",dp[v][p]); 52 }53 54 int main()55 {56     init();57     solve();    58     return 0;    59 } 

 

【四边形不等式】POJ1160[IOI2000]-Post Office