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 }