[luogu] P1220 关路灯

题目详情
题目分析:

  • dp[i][j][0]表示从编号i到j的灯关闭且老张关完最后一个灯在i位置,即区间左边时最小功耗。
  • dp[i][j][1]表示从编号i到j的灯关闭且老张关完最后一个灯在j位置,即区间右边时最小功耗。
  • power[i]是从第一个灯到第i个灯的总功耗(前缀和)。
  • 因为dp[i][j]必须从dp[i + 1][j]转移过来,所以当转移i + 1时i必须已经转移好了,所以i需要倒序遍历。
  • 关的灯一定是连续的,因为顺手关灯一定比路过不关功耗低。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int power[55], location[55], n, c, dp[55][55][2];
int calculate(int bigpos, int smallpos, int left, int right){
    return (location[bigpos] - location[smallpos]) * (power[left -1] + power[n] - power[right]);
}
int main()
{
    scanf("%d%d", &n, &c);
    memset(dp, 0x3f3f3f3f, sizeof(dp));//初始化
    for (int i = 1; i <= n; i++)
    {
        scanf("%d%d", &location[i], &power[i]);
        power[i] += power[i - 1];
    }
    dp[c][c][0] = dp[c][c][1] = 0;
    for (int j = c; j <= n; j++)
        for (int i = j - 1; i >= 1; i--){
            dp[i][j][0] = min(dp[i + 1][j][0] + calculate(i + 1, i, i + 1, j), dp[i + 1][j][1] + calculate(j, i, i + 1, j));
            dp[i][j][1] = min(dp[i][j - 1][0] + calculate(j, i, i, j - 1), dp[i][j - 1][1] + calculate(j, j - 1, i, j - 1));
        }
    printf("%d", min(dp[1][n][0], dp[1][n][1]));
}
发布了23 篇原创文章 · 获赞 0 · 访问量 956

猜你喜欢

转载自blog.csdn.net/weixin_45646006/article/details/105340910