SHADOWICENCXIX

导航

洛谷1220

dp三要素,状态定义,转移方程,边界条件!边界条件!边界条件!

不要以为方程出来了就万事大吉,还有边界条件!!!!!!

方程和楼下用的一样

dp[i][j][0]=min(dp[i+1][j][1]+sum(i+1,j)*(t[j]-t[i]),dp[i+1][j][0]+sum(i+1,j)*(t[i+1]-t[i]));

dp[i][j][1]=min(dp[i][j-1][1]+sum(i,j-1)*(t[j]-t[j-1]),dp[i][j-1][0]+sum(i,j-1)*(t[j]-t[i]));

其中dp[i][j][k]表示i到j区间的灯已灭,k=0老王在左端点,k=1老王在右端点。

sum(i,j)计算i到j的灯灭了以后剩余灯的功耗,t[i]是点i的距离。

然而我们发现,仅仅是dp[st][st][0]=0;dp[st][st][1]=0;

是不够的,这样在计算以st为起点和终点时,会有出发电灯亮着的鬼畜情况。。。

(因为方程鲁棒的把i+1,把j-1)

所以我们还需要专门针对i=st,j=st的转移方程!

dp[st-1][j][1]=dp[st-1][j-1][1]+sum(st-1,j-1)*(t[j]-t[j-1]);

dp[st-1][j][0]=dp[st-1][j][1]+sum(st-1,j)*(t[j]-t[st-1]);

dp[i][st-1][0]=dp[i+1][st-1][0]+sum(i+1,st-1)*(t[i+1]-t[i]);

dp[i][st-1][1]=dp[i][st-1][0]+sum(i,st-1)*(t[st-1]-t[i]);

上代码~

#include<stdio.h>
#include<algorithm>
using namespace std;
int n;int st;
int t[50];int w[50];
int dp[50][50][2];
int sum(int a,int b)
{
    int res=0;
    if(a>st-1)a=st-1;//粗暴的处理边界转移方程的非法情况,但无法处理普通转移的非法情况
    if(b<st-1)b=st-1;
    for(int i=0;i<n;i++)
    {
        if(i>=a&&i<=b)continue;
        res+=w[i];
    }
    //printf("sum(%d,%d)is%d\n",a,b,res);
    return res;
}
int main()
{
    scanf("%d%d",&n,&st);
    for(int i=0;i<n;i++)
    {
        scanf("%d%d",&t[i],&w[i]);
    }
    if(n==1)
    {
        printf("0");return 0;
    }
    dp[st-1][st-1][0]=0;dp[st-1][st-1][1]=0;//定义原点
    for(int j=st;j<n;j++)//从零开始的数组
    {
        dp[st-1][j][1]=dp[st-1][j-1][1]+sum(st-1,j-1)*(t[j]-t[j-1]);//递推以出发点为起点情况
        dp[st-1][j][0]=dp[st-1][j][1]+sum(st-1,j)*(t[j]-t[st-1]);
    }
    for(int i=st-2;i>=0;i--)
    {
        dp[i][st-1][0]=dp[i+1][st-1][0]+sum(i+1,st-1)*(t[i+1]-t[i]);//递推以出发点为终点情况
        dp[i][st-1][1]=dp[i][st-1][0]+sum(i,st-1)*(t[st-1]-t[i]);
    }
    for(int i=st-2;i>=0;i--)//没啥好说的dp,楼下讲的很详细
    {
        for(int j=st;j<n;j++)
        {
            dp[i][j][0]=
            min(dp[i+1][j][1]+sum(i+1,j)*(t[j]-t[i]),
            dp[i+1][j][0]+sum(i+1,j)*(t[i+1]-t[i]));
            dp[i][j][1]=
            min(dp[i][j-1][1]+sum(i,j-1)*(t[j]-t[j-1]),
            dp[i][j-1][0]+sum(i,j-1)*(t[j]-t[i]));
        }
    }
    /*for(int i=0;i<n;i++)
    {
        for(int j=0;j<n;j++)
        {
            printf("%-4d",dp[i][j][0]);
        }
        printf("\n");
    }
    printf("\n");
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<n;j++)
        {
            printf("%-4d",dp[i][j][1]);
        }
        printf("\n");
    }*/
    int res=min(dp[0][n-1][0],dp[0][n-1][1]);//不知道最后老王在路左还是路右,二者取其min
    printf("%d",res);
    return 0;//拜拜程序~
}

posted on 2017-10-15 17:04  SHADOWICENCXIX  阅读(108)  评论(0编辑  收藏  举报