ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

P1220 关路灯

2022-04-23 01:02:48  阅读:143  来源: 互联网

标签:路灯 int sum 老李 关掉 maxn P1220 转移


感谢所有AC

传送门

经验

       当遇到动点的$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;
}

 

标签:路灯,int,sum,老李,关掉,maxn,P1220,转移
来源: https://www.cnblogs.com/xqk0225/p/16181262.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有