G. Fascination Street
题意:
输入
n
(
250000
)
,
k
(
9
)
n(250000),k(9)
n(250000),k(9)
接下来一行
w
1
,
w
2
,
…
,
w
n
(
1
e
9
)
w_1,w_2,\dots,w_n(1e9)
w1,w2,…,wn(1e9)
问最多交换
k
k
k次,花费最小代价使全亮(本身亮或相邻一个亮即可)。
题解:
d
p
[
i
]
[
j
]
[
k
]
[
l
]
dp[i][j][k][l]
dp[i][j][k][l]表示到第
i
i
i个,欠
j
j
j个,还了
k
k
k个,后两个状态为
k
k
k的最小花费。
然后转移即可
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5e4+9;
int n,K,w[N];
#define ll long long
#define inf 0x3f3f3f3f3f3f3f3f
ll dp[N][11][11][4];//要开到11,开到10数组会爆,WA了
int main(){
// freopen("tt.in","r",stdin),freopen("tt.out","w",stdout);
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
cin>>n>>K;
for(int i=1;i<=n;i++)cin>>w[i];
memset(dp,0x3f,sizeof(dp));
dp[0][0][0][0]=0;
for(int i=0;i<n;i++){
for(int j=0;j<=K;j++)
for(int k=0;k<=K;k++)
for(int zt=0;zt<4;zt++){
if(dp[i][j][k][zt]==inf)continue;
if(zt==0){
if(i==0){
dp[i+1][j][k+1][0]=min(dp[i+1][j][k+1][0],dp[i][j][k][0]+w[i+1]);
dp[i+1][j][k][0]=min(dp[i+1][j][k][0],dp[i][j][k][0]);
}
dp[i+1][j+1][k][1]=min(dp[i+1][j+1][k][1],dp[i][j][k][0]);
dp[i+1][j][k][1]=min(dp[i+1][j][k][1],dp[i][j][k][0]+w[i+1]);
}else{
int tzt=(zt&1)<<1;
dp[i+1][j][k+1][tzt]=min(dp[i+1][j][k+1][tzt],dp[i][j][k][zt]+w[i+1]);
dp[i+1][j][k][tzt]=min(dp[i+1][j][k][tzt],dp[i][j][k][zt]);
tzt=tzt|1;
dp[i+1][j+1][k][tzt]=min(dp[i+1][j+1][k][tzt],dp[i][j][k][zt]);
dp[i+1][j][k][tzt]=min(dp[i+1][j][k][tzt],dp[i][j][k][zt]+w[i+1]);
}
}
}
ll ans=inf;
for(int i=0;i<=K;i++)
for(int j=1;j<=3;j++)ans=min(ans,dp[n][i][i][j]);//cout<<n<<" "<<i<<" "<<i<<" "<<j<<'\t'<<dp[n][i][i][j]<<endl;
cout<<ans<<endl;
return 0;
}