首页 > 其他分享 >洛谷题单指南-动态规划3-P1220 关路灯

洛谷题单指南-动态规划3-P1220 关路灯

时间:2024-05-15 18:30:39浏览次数:27  
标签:路灯 P1220 int 洛谷题 最后 功耗 关闭 一个

原题链接:https://www.luogu.com.cn/problem/P1220

题意解读:按坐标顺序排列1~n个路灯,每个路灯有不同的功耗,老张从位置c开始关灯,第一时间关掉c位置的灯,每次关掉一个灯之后,可以往右走、也可以往左走关下一个灯,老张速度是1m/s,求所有灯都关掉所消耗的最少功耗。

解题思路:

由题意分析,关闭一个范围内路灯的过程所消耗的功耗,可以由关闭该范围内一部分路灯的消耗推出,大概率是一个区间DP问题。

尝试进行DP问题分析:

1、状态表示

考虑最后一个关闭的路灯,根据题意,最后一个关闭的要么是头,要么是尾,有两种可能

所以预设两个状态:

设f[i][j]表示将第i ~ j的路灯关闭,且最后一个关闭的是i时,所消耗的总功耗;

设g[i][j]表示将第i ~ j的路灯关闭,且最后一个关闭的是j时,所消耗的总功耗;

设a[i]是第i个路灯的坐标,b[i]是第i个路灯的功耗。

2、状态转移

对于f[i][j],由于最后一个关闭的是i,因此可能有两种情况:从i+1到i、从j到i

  f[i][j] = min(f[i+1][j] + 关最后一个路灯的时间内所有亮着的灯的功耗,g[i+1][j] + 关最后一个路灯的时间内所有亮着的灯的功耗)

  对于情况一:f[i+1][j] + 关最后一个路灯的时间所有亮着的灯的功耗

    如何计算“关最后一个路灯的时间内所有亮着的灯的功耗”?

    

    如上图,最后一步,老张从i+1到i,所需时间为a[i+1] - a[i],此时所有未关闭的灯是1~i、j+1~n,总功耗就是时间 * 这些灯的功耗之和 

    如何求1~i、j+1~n的功耗之和?可以借助前缀和!

    设s[i]是b[1]~b[i]的和,即s[]是b[]的前缀和数组。

    则有“关最后一个路灯的时间内所有亮着的灯的功耗” = (a[i+1] - a[i]) * (s[i] + s[n] - s[j])

  对于情况二:g[i][j-1] + 关最后一个路灯的时间内所有亮着的灯的功耗

    如何计算“关最后一个路灯的时间内所有亮着的灯的功耗”?

  

    

    如上图,最后一步,老张从j到i,所需时间为a[j] - a[i],此时所有未关闭的灯是1~i、j+1~n,总功耗就是时间 * 这些灯的功耗之和 

    则有“关最后一个路灯的时间内所有亮着的灯的功耗” = (a[j] - a[i]) * (s[i] + s[n] - s[j])

所以有

f[i][j] = min(f[i+1][j] + (a[i+1] - a[i]) * (s[i] + s[n] - s[j]),g[i+1][j] + (a[j] - a[i]) * (s[i] + s[n] - s[j]))

同样的方式,可以得到

 

如上图,对应f[i][j-1] + (a[j] - a[i]) * (s[i-1] + s[n] - s[j-1])

如上图,对应g[i][j-1] + (a[j] - a[j-1]) * (s[i-1] + s[n] - s[j-1])

所以有

g[i][j] = min(f[i][j-1] + (a[j] - a[i]) * (s[i-1] + s[n] - s[j-1]), g[i][j-1] + (a[j] - a[j-1]) * (s[i-1] + s[n] - s[j-1]))

枚举时,可以先枚举区间长度,任何一次关闭动作要从一个路灯走到另一个路灯,区间长度至少是2,再枚举左端点,计算右端点即可。

3、初始化

f、g初始化为极大值,方便求最小值

对于位置c已经瞬间关闭,因此f[c][c] = g[c][c] = 0

4、结果

min ( f[1][n] , g[1][n] )

100分代码:

#include <bits/stdc++.h>
using namespace std;

const int N= 55;
int n, c;
int a[N], b[N], s[N]; //a[i]是第i个路灯的坐标,b[i]是第i个路灯的功耗,s是b的前缀和
int f[N][N]; //f[i][j]表示将第i ~ j的路灯关闭,且最后一个关闭的是i时,所消耗的总功耗
int g[N][N]; //g[i][j]表示将第i ~ j的路灯关闭,且最后一个关闭的是j时,所消耗的总功耗

int main()
{
    cin >> n >> c;
    for(int i = 1; i <= n; i++)
    {
        cin >> a[i] >> b[i];
        s[i] = s[i-1] + b[i];
    } 

    memset(f, 0x3f, sizeof(f));
    memset(g, 0x3f, sizeof(g));
    f[c][c] = g[c][c] = 0; //c路灯瞬间关闭,不消耗时间
    for(int len = 2; len <= n; len++)
    {
        for(int i = 1; i + len - 1 <= n; i++)
        {
            int j = i + len - 1;
            f[i][j] = min(f[i+1][j] + (a[i+1] - a[i]) * (s[i] + s[n] - s[j]), g[i+1][j] + (a[j] - a[i]) * (s[i] + s[n] - s[j]));
            g[i][j] = min(f[i][j-1] + (a[j] - a[i]) * (s[i-1] + s[n] - s[j-1]), g[i][j-1] + (a[j] - a[j-1]) * (s[i-1] + s[n] - s[j-1]));
        }
    }
    cout << min(f[1][n], g[1][n]);

    return 0;
}

 

标签:路灯,P1220,int,洛谷题,最后,功耗,关闭,一个
From: https://www.cnblogs.com/jcwy/p/18194495

相关文章

  • 洛谷题单指南-动态规划3-P4342 [IOI1998] Polygon
    原题链接:https://www.luogu.com.cn/problem/P4342题意解读:环中节点表示数字,边表示运算符,可以任意断一条边,其余节点两两按边的符号计算,求结果的最大值,以及最大值是断开那些边可以得到。解题思路:题意中有几个个关键信息:环形,节点数为n,边数为n任意断一条边,即可以从任意节点开始,......
  • 洛谷题单指南-动态规划3-P1070 [NOIP2009 普及组] 道路游戏
    原题链接:https://www.luogu.com.cn/problem/P1070题意解读:1~n个环形机器人工厂,相邻工厂之间的道路是1~n,每个时刻可以从任意工厂购买机器人,走不超过p时间,不同工厂购买机器人花费不同的金币,不同时刻走到不同道路也能得到不同的金币,问一共m时间,最多可以得到多少金币(需减去购买机器人......
  • 洛谷题单指南-动态规划3-P1063 [NOIP2006 提高组] 能量项链
    原题链接:https://www.luogu.com.cn/problem/P1063题意解读:本质上是一个环形石子合并问题,计算合并产生的最大能量。解题思路:对于环形DP问题,可以把环拆开,并复制2倍长度,然后用1~n的区间长度去枚举1、状态表示设structnode{inthead,tail}用于表示每一个项链节点,其中有头、尾......
  • 洛谷题单指南-动态规划3-P4170 [CQOI2007] 涂色
    原题链接:https://www.luogu.com.cn/problem/P4170题意解读:长度为n的字符串,每次可以将连续一段填为同一个字符,求要填成目标串的最少填涂次数。解题思路:1、状态表示:设s表示目标字符串,dp[i][j]表示将i~j涂成目标"颜色"的最少次数2、状态转移考虑i~j的两端,当i==j,说明只有一个......
  • 洛谷题单指南-动态规划3-P1140 相似基因
    原题链接:https://www.luogu.com.cn/problem/P1140题意解读:两个只包含A、C、G、T4个字符的序列,根据已经定义好的字符-字符的相似度,计算两个序列最大的相似度,两个序列必须每个字符都配对,如果字符不够,可以插入'-'代替。解题思路:本题要解决几个问题:1、状态表示既然有两个序列,设......
  • 洛谷题单指南-动态规划3-P1880 [NOI1995] 石子合并
    原题链接:https://www.luogu.com.cn/problem/P1880题意解读:计算n堆石子合并的最小、最大得分,只不过这n堆石子是环形的,也就是首、尾也相邻,是区间DP的升级版-环形DP问题。解题思路:如果是常规区间DP的方法:对于n堆石子,考察区间的长度范围是1~n先枚举左端点i,范围是1~n再计算右......
  • 洛谷题单指南-动态规划3-P3205 [HNOI2010] 合唱队
    原题链接:https://www.luogu.com.cn/problem/P3205题意解读:给定理想队形,计算初始队形的方案数。解题思路:对于给定理想队形,最后一个人插入有两种可能:从左边插入、从右边插入从左边插入,则意味着前一个数比当前数大,前一个数有可能在左边也有可能在右边从右边插入,则意味着前一个数......
  • 洛谷题单指南-动态规划3-Zuma
    原题链接:https://www.luogu.com.cn/problem/CF607B题意解读:从一组整数中取连续的回文子串,求最少几次可以取完。解题思路:状态表示:设dp[i][j]表示取i~j之间的回文子串所需的最少次数,a[i]表示第i个数状态转移:如果a[i]==a[j],dp[i][j]=dp[i+1][j-1],因为首尾如果相等,其必然可以......
  • 洛谷题单指南-动态规划3-P1775 石子合并(弱化版)
    原题链接:https://www.luogu.com.cn/problem/P1775题意解读:计算合并石子的最小代价,区间DP。解题思路:状态表示:dp[i][j]表示将第i~j堆石子合并的最小代价,m[i]表示第i堆石子质量,s[i]表示前i堆石子质量前缀和状态转移:考虑最后一次合并,设最后一次合并是将i~k合成的一堆与k+1~j合成......
  • 洛谷题单指南-动态规划2-P3147 [USACO16OPEN] 262144 P
    原题链接:https://www.luogu.com.cn/problem/P3147题意解读:将一组数据两两相邻且相同的合并,合并成一个数值+1的数,求合并后的最大值。解题思路:考虑合并后的最大数i,其最后一次必然是由两个i-1合并而来的设dp[i][j]表示以j为左端点,合并最大值为i时的右端点的下一个位置如图:dp[i......