Make The Fence Great Again(CF 1221 D)
题目大意
有\(q\)组询问,每组询问会给你一个由\(n\)块木板组成的篱笆,第\(i\)块木板的长度为\(a_i\),我们定义一个篱笆为好当且仅当这个篱笆相邻两块木板的长度都不相同,现在你可以操作若干次,每次可以把第\(i\)块木板加长一个单位的长度,花费为\(b_i\),每次问你使这个篱笆好的最小代价。\((1\le q,n\le3\times10^5,1\le a_i,b_i\le10^9,\sum n\le3\times10^5,ans_i\le10^{18})\)
思路
由于一块木板的两边最多只会有两块木板,于是每块木板最多加长两次,于是我们设\(dp[i][j]\)表示使前\(i\)块木板变好且第\(i\)块木板加长了\(j\)次所需要的最小代价,然后我们考虑转移:
\[if(a[i-1]+j\ne a[i]+k)dp[i][k]=\min(dp[i][k],dp[i-1][j]+b[i]\times k) \]然后这题就做完了。
代码
#include<bits/stdc++.h>
using namespace std;
long long dp[300005][3];
long long a[300005],b[300005];
int main()
{
int _=1;
scanf("%d",&_);
while(_--)
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%lld%lld",&a[i],&b[i]);
for(int i=1;i<=n;i++)for(int j=0;j<=2;j++)dp[i][j]=1e18;
for(int i=1;i<=n;i++)
for(int j=0;j<=2;j++)
for(int k=0;k<=2;k++)
if(a[i-1]+j!=a[i]+k)
dp[i][k]=min(dp[i][k],dp[i-1][j]+k*b[i]);
printf("%lld\n",min(dp[n][0],min(dp[n][1],dp[n][2])));
}
return 0;
}

浙公网安备 33010602011771号