Codeforces Gym102059 G. Fascination Street【DP】
Codeforces Gym102059 G. Fascination Street【DP】
这是赛后补的题 找了一些题解发现下面这篇最好理解,我用我自己的理解再写一遍详细的题解:
这是原作者:
————————————————
版权声明:本文为CSDN博主「Gene_INNOCENT」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_41552508/article/details/99082085
欢迎各位大佬指出错误,本人的第一篇题解
英文题面:

题目大意:
一条街上有N个点,需要从中选择一些点安装路灯,以照亮所有点,在一个点安装路灯可以照亮其左右点,每个点建立路灯都有对应的花费,并且你有K次机会交换某两个点建造路灯的花费,求整条路被照亮所需最小花费。(1≤N≤250000,0≤k≤9,0≤Wi≤1e9)
思路:
题目看起来就感觉像是个DP,如果没有“可以交换两个点的花费K次”的条件,就完全可以入手,只需两维:即一维表示当前点i的位置即照亮前i个点,另一维表示当前点的前一点i-1以及当前点i的三种状态:(0:亮——不亮)(1:不亮——不亮)(2:亮/不亮——亮)。
但是多了这个条件,如果按正常做法就会违背DP的一个必要条件:无后效性。
所以这玩意到底是不是DP啊!
是!不过得重新思考状态转移方程。既然其破坏了无后效性,那就把它整成满足无后效性。
首先,交换有意义必须交换双方一个没灯一个有灯。
其次,关于交换我们可以换着思考方式,不一定需要同时,我们可以先交后换,也可以先换了后交。什么意思呢,就是对于某个有路灯点a,我们先欠着不交,然后请后面某一不需要安装路灯的点b交b点的路灯费,也可以先交本来不需要路灯位置的路灯费,然后后面需要路灯的位置再欠路灯费,就相当与交换了。(核心)
思路有了,所以该怎么实现呢?
首先,我们构建DP状态,除了前面提到的两维,还需要加个两维,一位表示欠的路灯花费数,另一维表示还的路灯花费数的。即dp[i][j][k][l],i表示当前为第几个点,j表示欠了次,k表示还了几次,l表示i-1和i路灯的状态。状态转移见代码。
#include<bits/stdc++.h> using namespace std; typedef long long ll; #define N 250010 ll dp[N][10][10][3]; ll w[N]; ll n,K; ll ans=100000000000000000; solve() { memset(dp,0x3f,sizeof(dp)); dp[0][0][0][0]=0; for (int i=1;i<=n;i++) for (int j=0;j<=K;j++) for (int k=0;k<=K;k++) { dp[i][j][k][0]=dp[i-1][j][k][2];// 当前位(不亮——不亮) 只能由前一位的(不亮/亮——亮) 转移过来 if (k>0) dp[i][j][k][0]=min(dp[i][j][k][0],dp[i-1][j][k-1][2]+w[i]);//和上一行一样只不过还掉一个花费 dp[i][j][k][1]=dp[i-1][j][k][0];//当前位(不亮——不亮) 只能由前一位的(亮--不亮) 转移过来 if (k>0) dp[i][j][k][1]=min(dp[i][j][k][1],dp[i-1][j][k-1][0]+w[i]); //和上一行一样只不过还掉一个花费 for (int l=0;l<=2;l++) dp[i][j][k][2]=min(dp[i][j][k][2],dp[i-1][j][k][l]+w[i]);//当前位的(不亮/亮——亮)可以由前一位的任何一种状态转移过来 if (j>0) for (int l=0;l<=2;l++) dp[i][j][k][2]=min(dp[i][j][k][2],dp[i-1][j-1][k][l]);//与上面一个循环一样不过多欠一个花费 } for (int i=0;i<=K;i++) ans=min(ans,min(dp[n][i][i][0],dp[n][i][i][2]));//选择点亮了所有的n个点并且欠的和还的个数抵消的所有的值中的最小值 cout<<ans<<endl; } int main() { ios::sync_with_stdio(false); cin.tie(0);cout.tie(0); cin>>n>>K; for (int i=1;i<=n;i++) cin>>w[i]; solve(); return 0; }

浙公网安备 33010602011771号