1 条题解

  • 2
    @ 2021-11-14 10:11:04

    解题分析: 这是一道区间dp,首先需要知道端点,f(i,j)表示关i~j的路灯的时候,所有没被关的路灯消耗的能量和,那么在考虑一个端点的时候就不只需要考虑子状态之后一直走到端点所消耗的电能,因为之前消耗的电能会被子状态计算出来。 f(i,j,0)表示关掉i~j的电灯后最终停留在左端点所有电灯的最小功率,f(i,j,1)则是右端点

    先定义f(p,p,0)=f(p,p,1)=0; 其它的孤点全是inf(要令dp数字定义为-1) f(i,j,0)=min(f(i+1,j,0)+{i+1~i路程中剩下的电灯耗能综合},f(i+1,j,1)+(i~j)路程中所有电灯耗能总和) f(i,j,1)=min(f(i,j-1,1)+j-1~j路程中所有电灯消耗和,f(i,j-1,0)+i~j的路程中所有电灯消耗和 ) 然而耗能总和可通过前缀和的方式来完成

    
    #include<iostream>
    #include<stdio.h>
    #include<cstring>
    using namespace std;
    typedef long long LL;
    const int maxn=1005;
    const LL inf=1e9;
    int n,p;
    int d[maxn],w[maxn];
    LL sum[maxn],dp[maxn][maxn][2];
    void Init()
    {
        scanf("%d%d",&n,&p);
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d",&d[i],&w[i]);
            sum[i]=sum[i-1]+w[i];
        }
        memset(dp,-1,sizeof(dp));
    }
    LL f(int i,int j,int k)
    {
        if(dp[i][j][k]!=-1)
            return dp[i][j][k];
        if(i==j)
        {
            if(i==p)
                return dp[i][j][k]=0;
            else
                return dp[i][j][k]=inf;
        }
        if(k==0)
        {
            LL t1=f(i+1,j,0)+(d[i+1]-d[i])*(sum[i]+sum[n]-sum[j]);
            LL t2=f(i+1,j,1)+(d[j]-d[i])*(sum[i]+sum[n]-sum[j]);
            return dp[i][j][k]=min(t1,t2);
        }
        else 
        {
            LL t1=f(i,j-1,1)+(d[j]-d[j-1])*(sum[i-1]+sum[n]-sum[j-1]);
            LL t2=f(i,j-1,0)+(d[j]-d[i])*(sum[i-1]+sum[n]-sum[j-1]);
            return dp[i][j][k]=min(t1,t2);
        }
    }
    int main()
    {
        Init();
        cout<<min(f(1,n,0),f(1,n,1))<<endl;
        return 0;
    }
    
    • 1

    信息

    ID
    1443
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    8
    已通过
    3
    上传者