UVA - 11552 Fewest Flops
传送门:
题目大意:给你一个字符串,可以平均分成很多段,每一段之内的元素可以任意排序,最后再按原来的顺序把每一段拼起来,问最少的块数。(块:连续相同的一段字符成为一个块)
题解:
首先我们可以发现,每一个段之内先排好序,然后如果相邻的两端有相同的元素,就可以把这两个元素分别放在尾和首,就可以减少一个块了。于是一个贪心的做法油然而生:每次对于相邻的两段,如果有相同的元素,就可以把他们放在一起,也就是答案-1.但是显然有问题,如果这一个块与上一个,这一个块与下一个是相同的公共的字符,且有且仅有一种公共的字符,就不能减两次,但是如果这一个块只有一种元素,比如:“aaaaa”,那么又可以与两端共用。
MD贼麻烦啊!
于是放弃贪心,果断DP即可,因为如果我们知道26个字母每一个的状态,就没有那么多麻烦的特判了。算一下复杂度,O(len*26*26)也是可以的。
设dp[i][j]代表第i段与第i-1段之间以某一个元素相邻时,j这一个元素可以与后面的匹配的最下块数。也就是以j作为这一段的结尾,由上一段的结尾进行转移。
统计出每一个块的不同的元素的个数num[i]。以及每一个块是否有j元素has[i][j]。然后初始化dp[0][0~25]。从1开始,每次枚举前一个段结尾的元素,如果这个元素这一个段也有,那么可以放在一起,答案可以+num[i]-1。否则只能+num[i]。
要注意的是,如果前面结尾的等于当前枚举的,是不行的,因为当前枚举的也是结尾,两个结尾不能碰到一起,除非————只有一个元素。
#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#define RG register
#define LL long long
#define fre(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout);
using namespace std;
const int MAXN=,INF=0x3f3f3f3f;
int Case,top,k,len,ans;
int dp[MAXN][],num[MAXN];
bool has[MAXN][];
char s[MAXN];
int main()
{
scanf("%d",&Case);
while(Case--)
{
scanf("%d%s",&k,s);
len=strlen(s);
memset(num,,sizeof num);
memset(has,,sizeof has);
for(int i=;i<len;i++)
{
if(!has[i/k][s[i]-'a']) num[i/k]++;
has[i/k][s[i]-'a']=;
}
top=(len-)/k;
memset(dp,0x3f3f3f3f,sizeof dp);
for(int i=;i<;i++) dp[][i]=num[];
for(int i=;i<=top;i++)
for(int j=;j<;j++)
if(has[i-][j])
for(int l=;l<;l++)
if(has[i][l])
{
if(has[i][j] && (num[i]== || j!=l)) dp[i][l]=min(dp[i][l],dp[i-][j]+num[i]-);
else dp[i][l]=min(dp[i][l],dp[i-][j]+num[i]);
}
ans=INF;
for(int i=;i<;i++) ans=min(ans,dp[top][i]);
printf("%d\n",ans);
}
return ;
}
UVA - 11552 Fewest Flops的更多相关文章
- uva 11552 Fewest Flops 线性dp
// uva 11552 Fewest Flops // // 二维线性dp // // 首先,在该块必须是相同的来信.首先记录每块有很多种书 // 称为是counts[i]; // // 订购f[i ...
- UVa 11552 Fewest Flops (DP)
题意:给一个字符串,把它分为k块,每一块里面的字母可以任意的排序.最终字符串, 连续的一样的字母算作一个chunk,问总chunks最少是多少? 析:dp[i][j] 表示第 i 个块,第 j 位在末 ...
- UVA 11552 Fewest Flops(区间dp)
一个区间一个区间的考虑,当前区间的决策只和上一次的末尾有关,考虑转移的时候先统计当前区间出现过的字母以及种数ct 枚举上一个区间的末尾标号j,规定小于INF为合法状态,确定j之后看j有没有在当前的区间 ...
- 多维DP UVA 11552 Fewest Flop
题目传送门 /* 题意:将子符串分成k组,每组的字符顺序任意,问改变后的字符串最少有多少块 三维DP:可以知道,每一组的最少块是确定的,问题就在于组与组之间可能会合并块,总块数会-1. dp[i][j ...
- uva 11552 dp
UVA 11552 - Fewest Flops 一个字符串,字符串每 k 个当作一组,组中的字符顺序能够重组.问经过重组后改字符串能够编程最少由多少块字符组成.连续的一段字符被称为块. dp[i][ ...
- UVA 11552 四 Fewest Flops
Fewest Flops Time Limit:2000MS Memory Limit:0KB 64bit IO Format:%lld & %llu Submit Statu ...
- UVa 11552 DP Fewest Flops
题解 #include <cstdio> #include <cstring> #include <algorithm> using namespace std; ...
- UVA11552:Fewest Flops
发现如果只有一块就是种类的数目,也就是同种放在一起, 再考虑多块,如果违背的上面的规律,可以发现不会更优, 于是问题就是求在满足同种类放在一起的前提下,尽量使得相邻块的两端一模一样 然后dp一下就可以 ...
- UVa 11552 最小的块数(序列划分模型:状态设计)
https://vjudge.net/problem/UVA-11552 题意:输入一个正整数k和字符串S,字符串的长度保证为k的倍数.把S的字符按照从左到右的顺序每k个分成一组,每组之间可以任意重排 ...
随机推荐
- Yii自动生成项目
我喜欢尝试新鲜的东西.以前一直用gii生成工具,前几天突然发现用shell的方法,感觉很不错.特此总结一下yii的几个命令. gii的工具页面: - Controller Generator ...
- vue的安装以及语法介绍
#需要用到一个vue文件,还有一个自己的js文件main.js<!DOCTYPE html> <html lang="en"> <head> & ...
- MD5介绍及Windows下对文件做md5校验。
MD5介绍参考百度百科: 摘要如下: MD5 校验和(checksum)通过对接收的传输数据执行散列运算来检查数据的正确性. 一个散列函数,比如 MD5,是一个将任意长度的数据字符串转化成短的固定长度 ...
- JavaScript提高:001:ASP.NET使用easy UI
jQuery EasyUI是一组基于jQuery的UI插件集合.能够简洁的开发出功能多内容丰富的界面,而不须要开发人员自己费力的写那些复杂的js代码.本文简介在ASP.NET开发中引用这些js文件和样 ...
- 二阶段 三阶段 提交 Paxos
关于分布式事务.两阶段提交协议.三阶提交协议 - 文章 - 伯乐在线 http://blog.jobbole.com/95632/
- Python 中的字节与字节数组
Python 中的字节与字节数组 - Python - 伯乐在线 http://python.jobbole.com/84839/
- ul li menu
第一步:建立一个无序列表我们先建立一个无序列表,来建立菜单的结构.代码是: <ul><li><a href="1">首页</a>&l ...
- C++中的const完全解析
1. const修饰普通变量和指针 const修饰变量,一般有两种写法:const TYPE value;TYPE const value; 这两种写法在本质上是一样的.它的含义是:const修饰的类 ...
- C# 给窗体添加事件
1.https://zhidao.baidu.com/question/588485101.html
- 自己写的canvas 手写画板
<!DOCTYPE html> <html> <head> <title>canvas</title> <meta charset=& ...