POJ1160 Post Office-四边形不等式优化DP

方程

$\Large f(i,j)=min(f(i-1,k)+w(k+1,j))$

其中$w(i,j)$表示在$[i,j]$的村庄都去一个邮局的最小距离和

证明w满足四边形不等式

设$w_k(i,j)$表示$[i,j]$的村庄都去$k$村庄邮局的距离和

对于$\forall k$满足$w_k(i,j+1)=w(i,j+1)$都有$w_k(i+1,j)=w(i+1,j)$

(因为k只有选$i,j$的中间位置$w(i,j)$才是最小的)

$w(i,j)+w(i+1,j+1)\le w_k(i,j)+w_k(i+1,j+1)=w(i,j+1)+w(i+1,j)$

证明f满足四边形不等式

设$f_k(i,j)=f(i-1,k-1)+w(k,j)$

对于$\forall i\le i^{'}\le j\le j^{'}$,设$k=s(i,j^{'}),t=s(i^{'},j)$

 

1.如果$k\le t$

有$f(i,j)+f(i^{'},j^{'})\le f_k(i,j)+f_t(i^{'},j^{'})= f(i-1,k-1)+w(k,j)+f(i^{'}-1,t-1)+w(t,j^{'})$

因为w满足四边形不等式$f(i,j)+f(i^{'},j^{'})\le f(i-1,k-1)+w(k,j^{'})+f(i^{'}-1,t-1)+w(t,j)$

即$f(i,j)+f(i^{'},j^{'})\le f(i,j^{'})+f(i^{'},j)$

 

2.如果$k\gt t$

则只需证$f(i-1,t-1)+w(t,j)+f(i^{'}-1,k-1)+w(k,j^{'})\le f(i-1,k-1)+w(k,j^{'})+f(i^{'}-1,t-1)+w(t,j)$

设$k_1=s(i-1,k-1),k_2=s(i-2,k_1-1)……k_n=s(i-n,k_{n-1}-1)$

$t_1=s(i^{'}-1,t-1),t_2=s(i^{'}-2,t_1-1)……t_n=s(i^{'}-n,t_{n-1}-1)$

如果$k_1\le t_1$,就可以用上面的证明方法证出来

否则,递归本次证明直到得到求证$f(1,t_n-1)+f(i_{'}-i+1,k_n-1)\le f(1,k_n-1)+f(i_{'}-i+1,t_n-1)$

化简得$w(1,t_n-1)+f(i_{'}-i,t_{n+1}-1)+w(t_{n+1},k_n-1)\le w(1,k_n-1)+f(i_{'}-i,t_{n+1}-1)+w(t_{n+1},t_n-1)$

由w满足四边形不等式得$w(1,t_n-1)+w(t_{n+1},k_n-1)\le w(1,k_n-1)+w(t_{n+1},t_n-1)$

所以$f(i,j)+f(i^{'},j^{'})\le f(i,j^{'})+f(i^{'},j)$

证明$f(i,j)$的决策$s(i,j)$是单调的

1.设$k=s(i,j)$,对于所有$t\le k$

有$w(t,j)+w(k,j+1)\le w(t,j+1)+w(k,j)$

两边同时加上$f(i,t-1)+f(i,k-1)$得$f_t(i,j)+f_k(i,j+1)\le f_k(i,j)+f_t(i,j+1)$

因为$f_t(i,j)\ge f_k(i,j)$,所以$f_k(i,j+1)\le f_t(i,j+1)$

所以$s(i,j)\le s(i,j+1)$

 

2.设$k=s(i,j)$,对于所有$t\le k$

有$f(i,t-1)+f(i+1,k-1)\le f(i+1,t-1)+f(i,k-1)$

两边同时加上$w(t,j)+w(k,j)$得$f_t(i,j)+f_k(i+1,j)\le f_k(i,j)+f_t(i+1,j)$

因为$f_t(i,j)\ge f_k(i,j)$,所以$f_k(i+1,j\le f_t(i+1,j)$

所以$s(i,j)\le s(i+1,j)$

 

代码

#include<cstdio>
#include<cstring>
using namespace std;
#define maxn 305
#define maxp 40
int f[maxp][maxn],s[maxp][maxn],w[maxn][maxn],a[maxn];
int main(){
    memset(f,0x3f,sizeof(f));
    int n,p;scanf("%d%d",&n,&p);
    for(int i=1;i<=n;i++)scanf("%d",a+i);
    for(int i=1;i<=n;i++){
        for(int j=i+1;j<=n;j++){
            w[i][j]=w[i][j-1]+a[j]-a[(i+j)/2];
        }
        s[0][i]=1;
    }
    f[0][0]=0;
    for(int i=1;i<=p;i++){
        f[i][i]=0;s[i][i]=i;s[i][n+1]=n;
        for(int j=n;j>i;j--){
            for(int k=s[i-1][j];k<=s[i][j+1];k++){
                if(f[i][j]>f[i-1][k-1]+w[k][j]){
                    f[i][j]=f[i-1][k-1]+w[k][j];s[i][j]=k;
                }
            }
        }
    }
    printf("%d",f[p][n]);
    return 0;
} 
posted @ 2018-05-03 21:35  Bennettz  阅读(181)  评论(0编辑  收藏  举报