luogu P1220 关路灯

题目链接:luogu P1220 关路灯

题目大意:

题解:
一道区间DP题。
(dp[i][j])表示第(i)盏路灯到第(j)盏路灯都关掉后,剩下路灯都开着的情况下消耗的最小电能。
由于可以掉头走或者继续走下去,所以增加一维,(dp[i][j][0])表示关完这一段的路灯后留在第(i)盏路灯,(dp[i][j][1])表示关完这一段的路灯后留在第(j)盏路灯。
状态转移方程:

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

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

由于不知道关完所有路灯之后是留在哪一端,所以答案为(dp[1][n][0],dp[1][n][1])中较小者。

#include <iostream>
#include <cstring>
using namespace std;
#define io_speed_up ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)

int dis[55], p[55], sum[55], n, c, dp[55][55][2];

int main() {
	io_speed_up;
	cin >> n >> c;
	memset(dp, 0x3f, sizeof(dp));
	for (int i = 1; i <= n; ++i) {
		cin >> dis[i] >> p[i];
		sum[i] = sum[i - 1] + p[i];
	}
	dp[c][c][0] = dp[c][c][1] = 0;
	for (int l = 2; l <= n; ++l) {
		for (int i = 1; i + l - 1 <= n; ++i) {
			int j = i + l - 1;
			dp[i][j][0] = min(dp[i + 1][j][0] + (dis[i + 1] - dis[i]) * (sum[i] + sum[n] - sum[j]), 
				dp[i + 1][j][1] + (dis[j] - dis[i]) * (sum[i] + sum[n] - sum[j]));
			dp[i][j][1] = min(dp[i][j - 1][0] + (dis[j] - dis[i]) * (sum[i - 1] + sum[n] - sum[j - 1]),  
				dp[i][j - 1][1] + (dis[j] - dis[j - 1]) * (sum[i - 1] + sum[n] - sum[j - 1]));
		}
	}
	cout << min(dp[1][n][0], dp[1][n][1]);
	return 0;
}
原文地址:https://www.cnblogs.com/IzumiSagiri/p/14022104.html