POJ1160 Post Office 区间DP/区间DP+四边形不等式优化

POJ1160 Post Office

/*POJ1160 区间DP
状态转移方程:dp[i][j]=min(dp[i][j],dp[k][j-1]+add[k+1][i])
32MS   752K		
*/
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
const int MAX1=303;
const int MAX2=33;
const int INF=0x3f3f3f3f;
int a[MAX1],dp[MAX1][MAX2],add[MAX1][MAX1];
void read (int &x)//读入优化
{
    int f=1;x=0;char s=getchar();
    while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
    while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
    x*=f;
}
void init (int n,int m)
{
    for (int k=1;k<=n;k++)
        read(a[k]);
    for (int i=1;i<n;i++)
        for (int j=i+1;j<=n;j++)
            add[i][j]=add[i][j-1]+a[j]-a[(i+j)>>1];//区间i~j中建一个站的最优值是区间中点到各点的距离的和
    for (int k=1;k<=n;k++)
        dp[k][1]=add[1][k];//初始化1~k建一个站的最优值即为add[1][k]
}
int main ()
{
    int n,m;
    read(n);read(m);
    init(n,m);
    for (int i=2;i<=m;i++)
    {
        for (int j=n;j>i;j--)
        {
            dp[j][i]=INF;//求最小值
            for (int k=i;k<j;k++)
                if(dp[j][i]>dp[k][i-1]+add[k+1][j])
                    dp[j][i]=dp[k][i-1]+add[k+1][j];
        }
    }
    printf ("%d\n",dp[n][m]);//最终状态
    return 0;
}

/*POJ1160 区间DP+四边形不等式优化
状态转移方程:dp[i][j]=min(dp[i][j],dp[k][j-1]+add[k+1][i])
16MS   792K
*/
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
const int MAX1=303;
const int MAX2=33;
const int INF=0x3f3f3f3f;
int a[MAX1],dp[MAX1][MAX2],add[MAX1][MAX1],s[MAX1][MAX2];//s[i][j]保存此状态取到最优值的位置(区间上)
void read (int &x)//读入优化
{
    int f=1;x=0;char s=getchar();
    while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
    while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
    x*=f;
}
void init (int n,int m)
{
    for (int k=1;k<=n;k++)
        read(a[k]);
    for (int i=1;i<n;i++)
        for (int j=i+1;j<=n;j++)
            add[i][j]=add[i][j-1]+a[j]-a[(i+j)>>1];//区间i~j中建一个站的最优值是区间中点到各点的距离的和
    for (int k=1;k<=n;k++)
    {
        dp[k][1]=add[1][k];//初始化1~k建一个站的最优值即为add[1][k]
        s[k][1]=1;//起点(随题意而定)
    }
}
int main ()
{
    int n,m;
    read(n);read(m);
    init(n,m);
    for (int i=2;i<=m;i++)
    {
        s[n+1][i]=n;//终点(随题意而定)
        for (int j=n;j>i;j--)//四边形优化要求n开始
        {
            dp[j][i]=INF;//求最小值
            for (int k=s[j][i-1];k<=s[j+1][i];k++)//四边形优化(前后随题意而定)
                if(dp[j][i]>dp[k][i-1]+add[k+1][j])
                {
                    dp[j][i]=dp[k][i-1]+add[k+1][j];
                    s[j][i]=k;//更新位置
                }
        }
    }
    printf ("%d\n",dp[n][m]);//最终状态
    return 0;
}

猜你喜欢

转载自blog.csdn.net/nrtostp/article/details/80185980