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;
}
posted @ 2020-11-22 22:53  ZZHHOOUU  阅读(98)  评论(0编辑  收藏  举报