POJ1160 Post Office 四边形不等式优化

  题目链接:http://poj.org/problem?id=1160

  f[i][j]表示前 i 个村庄放 j 个邮局的最小花费,w[i][j]表示 i-j 村庄之间放一个邮局的最小花费,则转移方程:f[i][j]= Min{ f[k][j-1] + w[k+1][i] },把f[i][j]转换一下,表示前 j 个村庄放 i 个邮局的最小花费,则 f[i][j]=Min{ f[i-1][k] + w[k+1][i] }。

  四边形不等式优化有如下定理:

    1.当决策代价函数w[i][j]满足w[i][j]+w[i’][j’]<=w[I;][j]+w[i][j’](i<=i’<=j<=j’),w满足四边形不等式.当函数w[i][j]满足w[i’][j]<=w[i][j’] i<=i’<=j<=j’),w关于区间包含关系单调.

    2.如果状态转移方程m且决策代价w满足四边形不等式的单调函数(可以推导出m亦为满足四边形不等式的单调函数),则可利用四边形不等式推出最优决策s的单调函数性,从而减少每个状态的状态数,将算法的时间复杂度由原来的O(n^3)降低为O(n^2).方法是通过记录子区间的最优决策来减少当前的决策量.:

s[i][j]=max{k | ma[i][j] = m[i][k-1] + m[k][j] + w[i][j]}

由于决策s具有单调性,因此状态转移方程可修改为:

  因此只要证明w满足凸和包含关系就可以用四边形不等式优化了。

 1 //STATUS:C++_AC_16MS_584KB
 2 #include<stdio.h>
 3 #include<string.h>
 4 #define min(a,b) ( (a)<(b)?(a):(b) )
 5 const int MAX1=310,MAX2=35,INF=10000000;
 6 int dp[MAX1][MAX2],sum[MAX1][MAX1],p[MAX1],P,V;
 7 int main()
 8 {
 9 //    freopen("in.txt","r",stdin);
10     int i,j,k,min;
11     while(~scanf("%d%d",&V,&P))
12     {
13         min=0x7fffffff;
14         memset(sum,0,sizeof(sum));
15         for(i=1;i<=V;i++)
16             scanf("%d",&p[i]);
17 
18         for(i=1;i<V;i++){
19             for(j=i+1;j<=V;j++){
20                 sum[i][j]=sum[i][j-1]+p[j]-p[(i+j)/2];
21             }
22         }
23         for(i=1;i<=V;i++){
24             dp[i][1]=sum[1][i];
25             dp[i][i]=0;
26         }
27 
28         for(j=2;j<=P;j++){
29             for(i=j+1;i<=V;i++){
30                 dp[i][j]=INF;
31                 for(k=j-1;k<i;k++)
32                      dp[i][j]=min(dp[i][j],dp[k][j-1]+sum[k+1][i]);
33             }
34         }
35 
36         printf("%d\n",dp[V][P]);
37     }
38     return 0;
39 }
原文地址:https://www.cnblogs.com/zhsl/p/2982362.html