POJ-1160 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 }

 

你可能感兴趣的:(Office)