【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; }