洛谷 P1220 关路灯 区间dp
题面
https://www.luogu.com.cn/problem/P1220
分析
考虑区间
令为已经关了的灯,当前位置在的最少功耗;
为已经关了的灯,当前位置在的最少功耗。
可以发现,因为状态是区间的扩大,故只有如下情况:
若当前为,上一个状态要么是从点向左走了格,即;或者是从点向左走了格,即
若当前为,上一个状态要么是从点向右走了格,即;或者是从点向右走了格,即
考虑的计算:
可以发现,cost的计算与跑动的时间、目前仍在运行的灯数均有关。当从跑到时,且当前的灯已被关闭时:
目前仍在运行的灯数(功率)为,跑动时间为。
故cost函数可以写为:
int count(int x, int y, int l, int r) {
return (pos[y] - pos[x]) * (sum[l - 1] + (sum[n] - sum[r]));
}
Code
#include<iostream>
#include<cstdio>
#include<cstring>
const int maxn = 50 + 10;
const int inf = 0x3f3f3f3f;
int n, c;
int pos[maxn], p[maxn], sum[maxn];
int dp[maxn][maxn][2];
int count(int x, int y, int l, int r) {
return (pos[y] - pos[x]) * (sum[l - 1] + (sum[n] - sum[r]));
}
int main() {
memset(dp, inf, sizeof(dp));
scanf("%d%d", &n, &c);
for (int i = 1; i <= n; i++) {
scanf("%d%d", &pos[i], &p[i]);
sum[i] = sum[i - 1] + p[i];
//dp[i][i][0]=dp[i][i][1]=0;
}
dp[c][c][0] = dp[c][c][1] = 0;
for (int len = 2; len <= n; len++)
for (int i = 1; i + len - 1 <= n; i++) {
int j = i + len - 1;
dp[i][j][0] = std::min(dp[i + 1][j][0] + count(i, i + 1, i + 1, j),
dp[i + 1][j][1] + count(i, j, i + 1, j));
dp[i][j][1] = std::min(dp[i][j - 1][1] + count(j - 1, j, i, j - 1),
dp[i][j - 1][0] + count(i, j, i, j - 1));
}
int ans = std::min(dp[1][n][0], dp[1][n][1]);
printf("%d", ans);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!