P1220 关路灯

发布时间:2022-06-08 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了P1220 关路灯脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。

感谢所有AC

传送门

经验

@H_304_13@       当遇到动点的$dp$问题时,需要注意动点所在位置对状态转移的影响,如果有影响,可以适当考虑增加一个维度用来表示动点地位置状态。

思路

       由于老李关掉灯的时间忽略不计,因此老李所过之处一定是所有灯全灭,那么关灯就可以有两种选择,一种是沿着现在行进的方向继续关下一盏灯,另一种是掉头去关另一盏灯。可以用状态 $f(i,j)$ 来表示老张从 $i$ 走到 $j$ 时灯的总能耗。接下来考虑状态转移,即关灯的选择。

       因为老李的位置未知,初步判断 $f(i,j)$ 可以分别由 $f(i+1,j)$ 和 $f(i,j+1)$ ,代表着老李两个不同的行进方向。但是问题又来了,转移的时候,并不知道老李的位置,可是老李的位置又和灯的耗能息息相关,因此我们必须要表示出老李的位置。于是定义状态 $f(i,j,0)$ 表示老李关掉了 $i$ 到 $j$ 的灯且最后站在 $i$ 点时灯的总能耗,$f(i,j,1)$ 表示老李关掉了 $i$ 到 $j$ 的灯且最后站在 $j$ 点时灯的总能耗。

        $f(i,j,0)$ 可以由 $f(i+1,j,0)$ 转移(向左走一步关掉 $i$ 处的灯),也可以由 $f(i+1,j,1)$ 转移(掉头关掉 $i$ 处的灯),而$f(i,j,1)$ 同理,;转移时根据老李的行走时间计算灯的耗能。

代码

#include<iostream>
#include<cstring>
#define maxn 60
using namespace std;
int n, c, a[maxn], sum[maxn], f[maxn][maxn][2];
int main(void)
{
	ios::sync_wITh_stdio(false);
	cin.tie(0); cout.tie(0);
	cin >> n >> c;
	for (int i = 1; i <= n; i++)
	{
		cin >> a[i] >> sum[i];
		sum[i] += sum[i - 1];
	}
	memset(f, 5, sizeof(f));
	f[c][c][0] = f[c][c][1] = 0;
	for(int L=2;L<=n;L++)
		for (int i = 1, j = i + L - 1; j <= n; i++, j++)
		{
			f[i][j][0] = min(f[i + 1][j][0] + (a[i + 1] - a[i]) * (sum[n] - sum[j] + sum[i]),
				f[i + 1][j][1] + (a[j] - a[i]) * (sum[n] - sum[j] + sum[i]));
			f[i][j][1] = min(f[i][j - 1][0] + (a[j] - a[i]) * (sum[n] - sum[j - 1] + sum[i - 1]),
				f[i][j - 1][1] + (a[j] - a[j - 1]) * (sum[n] - sum[j - 1] + sum[i - 1]));
		}
	cout << min(f[1][n][1], f[1][n][0]);
	return 0;
}

 

脚本宝典总结

以上是脚本宝典为你收集整理的P1220 关路灯全部内容,希望文章能够帮你解决P1220 关路灯所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。