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个分成一组,每组之间可以任意重排 ...
随机推荐
- 【转载】TCP的三次握手(建立连接)和四次挥手(关闭连接)
建立连接: 理解:窗口和滑动窗口TCP的流量控制 TCP使用窗口机制进行流量控制 什么是窗口? 连接建立时,各端分配一块缓冲区用来存储接收的数据,并将缓冲区的尺寸发送给另一端 接收方发送的确认信息中包 ...
- uva 1567 - A simple stone game(K倍动态减法游戏)
option=com_onlinejudge&Itemid=8&page=show_problem&problem=4342">题目链接:uva 1567 - ...
- 关于MP4视频拖动的原理与分析(一)
本来想说说关于mp4和一些常见视频文件格式方面的历史. 如今想想没啥必要.毕竟本文是在讲关于mp4点播拖动方面的技术细节. 绪论,前言神马的显得有点多余. 说起MP4.不得不提"Digita ...
- CentOS笔记-系统概述
Linux系统的启动过程并不是大家想象中的那么复杂,其过程可以分为5个阶段: 内核的引导. 当计算机打开电源后,首先是BIOS开机自检,按照BIOS中设置的启动设备(通常是硬盘)来启动. 操作系统接管 ...
- 关闭SVN服务
关闭TSVNCache.exe进程 在Windows下使用SVN,通常都会安装TortoiseSVN,安装后会有一个TSVNCache.exe的进程驻留内存,这个进程会定时地去扫描Subversion ...
- 在线安装Ganglia3.6.0,nginx+php搭建gweb,绝对通过
环境:CentOS6.5 minimal 目标:安装Ganglia核心组件(gmond, gmetad, gmetric, gstat, libganglia).Ganglia web 准备 yum增 ...
- var和let的区别(详解)
1. 作用域 通过var定义的变量,作用域是整个封闭函数,是全域的 . 通过let定义的变量,作用域是在块级或是子块中. function varTest() { var x = 1; if (tru ...
- luogu2398 SUM GCD
题目大意:求sum i(1->n) (sum j(1->n) (gcd(i,j))). 对于每对(i,j)都来一次gcd很慢,但是我们知道,一个约数i在1~n范围内是n/i个数的约数.gc ...
- JS是否确认提示 +页面跳转
JS友好提示 +页面跳转 function logout()...{if (confirm("你确定要注销身份吗?是-选择确定,否-选择取消"))...{window.locati ...
- 百度自然语言处理api用法
def words url = "https://aip.baidubce.com/rpc/2.0/nlp/v1/lexer?access_token=1111111" param ...