題目鏈接:https://nanti.jisuanke.com/t/43371
題目大意:有n個數。給你一個k和s。每個數字可以改變成0-s。讓你以相鄰的k個爲一組[a[1]…a[k]], [a[2]…a[k+1]]…。問使每一組的和爲s。至少需要改變多少個數。
根據題目的條件這個數組最後的樣子一定是以k爲循環節。a[1]=a[k+1],a[2]=a[k+2]…
那麼就是有k組數。我們把每組數出現的次數計爲:size。那麼就可以變成一個容量爲S的分組揹包。出現的數組體積爲數字。貢獻爲size(如果把這組都變成這個數字,那麼這組可以不用改變的數字個數)。
最後n-f[n][s]就是答案。
如果我們枚舉X。複雜度就是是不可以的。
#include<bits/stdc++.h>
#define LL long long
using namespace std;
int a[5005];
int siz[5005][5005];
vector<int> v[5005];
int f[5005][5005];
int g[5005][5005];
int main(){
int n, k, s;scanf("%d%d%d", &n, &k, &s);
for(int i=0; i<n; i++){
scanf("%d", &a[i]);
if(siz[i%k+1][a[i]]==0){
v[i%k+1].push_back(a[i]);
}
siz[i%k+1][a[i]]++;
}
for(int i=1; i<=s; i++){
f[0][i]=-1<<30;
}
f[0][0]=0;
for(int i=1; i<=k; i++){
for(int j=0; j<=s; j++){
g[i][j]=g[i-1][j];
}
for(int j=0; j<=s; j++){
g[i][j]=max(j?g[i][j-1]:0, f[i-1][j]);
}
for(int j=0; j<=s; j++){
//f[i][j]=f[i-1][j]+siz[i][0];
for(int k=0; k<v[i].size(); k++){
if(j>=v[i][k]){
f[i][j]=max(f[i][j], f[i-1][j-v[i][k]]+siz[i][v[i][k]]);
}
else{
f[i][j]=max(f[i][j], f[i-1][j]);
}
}
}
for(int j=0; j<=s; j++){
f[i][j]=max(f[i][j], g[i][j]);
}
}
cout<<n-f[k][s]<<endl;
return 0;
}