P4749 【CERC2017】Kitchen Knobs
LiYueLin06 · · 题解
P4749 Kitchen Knobs
记录每个字符串以第
先差分,操作就变成了选两个位置
如果只选一个位置,可以直接加减变成
首先可以把
这样操作后最多三组中各剩下一种数字,考虑对这三种数字的配对方法dp。
记
每次选择加入一个数,如果当前三种数分别乘上选择数量再相加得到的和为
例如:
选的数是:2 2 3
step1: 0 4 3
step2: 0 0 0
比一个个消少了一步
最后答案为
复杂度
另外要注意,原字符串每位都相同时,怎么转都是一样的,它的值随意,不用变成
#include<iostream>
#include<stdio.h>
using namespace std;
short f[502][502][502];
int cnt[5],n,m,num[7],st[502],rst[5];
char c[10];
bool cmp(int x,int y){
for(int i=x,j=y,k=0;k<7;k++,i=(i+1)%7,j=(j+1)%7){
if(c[i]>c[j]) return 0;
if(c[i]<c[j]) return 1;
}
return 0;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%s",c);
bool flag=1;
for(int j=1;j<7;j++){
if(c[j]!=c[j-1]){
flag=0;break;
}
}
if(flag) continue;//每位相同,怎么转都行,没有差分数组的限制
int mx=0;
for(int j=1;j<7;j++){
if(cmp(mx,j)){
mx=j;
}
}
st[++m]=mx;
}
for(int i=1;i<=m;i++){
num[(st[i]-st[i-1]+7)%7]++;
}
int ans=0;
for(int i=1;i<=3;i++){
if(num[i]<num[7-i]){
ans+=num[i];
rst[i]=7-i;
cnt[i]=num[7-i]-num[i];
}
else{
ans+=num[7-i];
rst[i]=i;
cnt[i]=num[i]-num[7-i];
}
}
int sum=cnt[1]+cnt[2]+cnt[3];
for(int i=0;i<=cnt[1];i++){
for(int j=0;j<=cnt[2];j++){
for(int k=0;k<=cnt[3];k++){
if(i) f[i][j][k]=max(f[i][j][k],f[i-1][j][k]);
if(j) f[i][j][k]=max(f[i][j][k],f[i][j-1][k]);
if(k) f[i][j][k]=max(f[i][j][k],f[i][j][k-1]);
if((i*rst[1]+j*rst[2]+k*rst[3])%7==0&&(i+j+k>0)){
f[i][j][k]++;
}
}
}
}
ans+=sum-f[cnt[1]][cnt[2]][cnt[3]];
printf("%d\n",ans);
return 0;
}