【luogu1220】关路灯

https://www.luogu.org/problem/show?pid=1220

假如当前老张在a处跑去关掉b处的路灯,那么a与b之间的路灯都可以顺手关掉。因此每一时刻关掉的路灯必定是连续的。

f(i,j,0)表示i~j的路灯全部关掉且老张处于最左边时的耗电。f(i,j,1)表示i~j的路灯全部关掉且老张处于最右边时的耗电。

状态转移方程:

f(i,j,0)=min{
     f(i+1,j,0)+(dist[i+1]-dist[i])*(watt[1,i]+watt[j+1,n]),
     f(i+1,j,1)+(dist[j]-dist[i])*(watt[1,i]+watt[j+1,n])
}

f(i,j,1)=min{
    f(i,j-1,1)+(dist[j]-dist[j-1])*(watt[1,i-1]+watt[j,n]),
     f(i,j-1,0)+(dist[j]-dist[i])*(watt[1,i-1]+watt[j,n])
}

watt[i,j]表示i~j的路灯的总功率。

边界条件:f(i,i,0 or 1)=∞,f(c,c,0 or 1)=0

∞不能太大,因为要用来运算。

#include <iostream>
#define maxn 60
#define inf 0x7ffffffffffffff0
using namespace std;
int n, c;
int dist[maxn], wattsum[maxn];
unsigned long long dp0[maxn][maxn], dp1[maxn][maxn];
int main()
{
    cin >> n >> c;
    for(int i = 1; i <= n; i++)
    {
        cin >> dist[i] >> wattsum[i];
        wattsum[i] += wattsum[i - 1];
    }

    for(int i = 1; i <= n; i++)
        dp0[i][i] = dp1[i][i] = inf;
    dp0[c][c] = dp1[c][c] = 0;
    for(int len = 2; len <= n; len++)
    {
        for(int i = 1, j = len; j <= n; i++, j++)
        {
            dp0[i][j] = min(dp0[i + 1][j] + (dist[i + 1] - dist[i]) * (wattsum[i] - wattsum[0] + wattsum[n] - wattsum[j]), dp1[i + 1][j] + (dist[j] - dist[i]) * (wattsum[i] - wattsum[0] + wattsum[n] - wattsum[j]));
            dp1[i][j] = min(dp1[i][j - 1] + (dist[j] - dist[j - 1]) * (wattsum[i - 1] - wattsum[0] + wattsum[n] - wattsum[j - 1]), dp0[i][j - 1] + (dist[j] - dist[i]) * (wattsum[i - 1] - wattsum[0] + wattsum[n] - wattsum[j - 1]));
        }
    }
    cout << min(dp0[1][n], dp1[1][n]) << endl;
    return 0;
}
原文地址:https://www.cnblogs.com/ssttkkl/p/7073461.html