您的位置:首页 > Web前端

UVa11552 - Fewest Flops(dp)

2017-10-22 11:02 471 查看
题目链接

简介:

把长度为S的字符串从左到右,每k个为一组,同组之间可以互相交换位置

使得重排后的字符串包含尽量少的块,其中每个块为连续的相同字符

分析:

我设计的状态是这样的

f[i][j] 表示第i组最后的字符为j,得到的最小块数

转移就需要枚举当前组的最后字符和上一组的最后字符

d=f[i-1][p]+(第i组包含的不同字符)

if (第i组中有p这个字符而且j!=p) d - -;

if (第i组中全是p这个字符) d - -;

f[i][j]=min{d}

一段区间内每个字符的出现次数,用前缀和维护

1A,震惊!!!

//这里写代码片
#include<cstdio>
#include<cstring>
#include<iostream>

using namespace std;

char s[1003];
int sum[1003][27],len,f[1003][27],k;

void doit()
{
int i,j,p,q;
int tt=0;

memset(f,0x33,sizeof(f));

for (i=0;i<26;i++)
if (sum[k][i]) tt++;
for (i=0;i<26;i++)
if (sum[k][i])
f[1][i]=tt;

for (i=2;i<=len/k;i++)
{
tt=0;
for (j=0;j<26;j++) if (sum[i*k][j]-sum[(i-1)*k][j]) tt++;

for (j=0;j<26;j++)
if (sum[i*k][j]-sum[(i-1)*k][j])
for (p=0;p<26;p++)
if (sum[(i-1)*k][p]-sum[(i-2)*k][p])
{
int d=f[i-1][p]+tt;
if (sum[i*k][p]-sum[(i-1)*k][p]&&(p!=j||sum[i*k][p]-sum[(i-1)*k][p]==k)) d--;
f[i][j]=min(f[i][j],d);
}
}

int ans=1e9;
for (i=0;i<26;i++) ans=min(ans,f[len/k][i]);
printf("%d\n",ans);
}

int main()
{
int T;
scanf("%d",&T);
while (T--)
{
scanf("%d",&k);
scanf("%s",s+1);
len=strlen(s+1);
memset(sum,0,sizeof(sum));
for (int i=1;i<=len;i++)
{
for (int j=0;j<26;j++)
sum[i][j]=sum[i-1][j];
sum[i][s[i]-'a']++;
}

doit();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: