【题解】

  区间DP.  设f[i][j]表示i~j的最小代价。再枚举中间点k,很容易想到转移方程为f[i][j]=min(f[i][j],f[i][k]+f[k][j]),同时如果i~k可以通过重复获得i~j,那么f[i][j]=min(f[i][j],f[i][k]+len(x)+2),这里的len(x)是指重复次数在十进制下有多少位。

 #include<cstdio>
#include<algorithm>
#include<cstring>
#define LL long long
#define rg register
#define N 200
using namespace std;
int n,m,f[N][N];
char s[N];
inline int read(){
int k=,f=; char c=getchar();
while(c<''||c>'')c=='-'&&(f=-),c=getchar();
while(''<=c&&c<='')k=k*+c-'',c=getchar();
return k*f;
}
inline bool check(int l,int r,int end){
int l1=r-l+,l2=end-l+;
if(l2%l1) return ;
m=l2/l1;
for(rg int i=;i<=m;i++){
int st=l+(i-)*l1;
for(rg int j=;j<l1;j++) if(s[l+j]!=s[st+j]) return ;
}
return ;
}
inline int qlen(int x){
int cnt=;
while(x){
x/=;
cnt++;
}
return cnt;
}
int main(){
scanf("%s",s+); n=strlen(s+);
for(rg int i=;i<=n;i++)
for(rg int j=i;j<=n;j++) f[i][j]=j-i+;
for(rg int l=;l<=n;l++){
for(rg int i=;i+l-<=n;i++){
int j=i+l-;
for(rg int k=i;k<=j;k++){
f[i][j]=min(f[i][j],f[i][k]+f[k+][j]);
if(check(i,k,j)){
f[i][j]=min(f[i][j],f[i][k]++qlen(m));
// printf("%d %d %d\n",i,k,j);
}
}
}
}
printf("%d\n",f[][n]);
return ;
}

  输出方案的版本。

 #include<cstdio>
#include<algorithm>
#include<cstring>
#define LL long long
#define rg register
#define N 200
using namespace std;
int n,m,f[N][N],ans[N],from[N][N];
char s[N];
inline int read(){
int k=,f=; char c=getchar();
while(c<''||c>'')c=='-'&&(f=-),c=getchar();
while(''<=c&&c<='')k=k*+c-'',c=getchar();
return k*f;
}
inline bool check(int l,int r,int end){
int l1=r-l+,l2=end-l+;
if(l2%l1) return ;
m=l2/l1;
for(rg int i=;i<=m;i++){
int st=l+(i-)*l1;
for(rg int j=;j<l1;j++) if(s[l+j]!=s[st+j]) return ;
}
return ;
}
inline int qlen(int x){
int cnt=;
while(x){
x/=;
cnt++;
}
return cnt;
}
void out(int l,int r){
if(f[l][r]==r-l+){
for(rg int i=l;i<=r;i++) printf("%c",s[i]);
return;
}
int k=from[l][r];
if(check(l,k,r)){
printf("%d(",m);
out(l,k);
printf(")");
}
else{
out(l,k); out(k+,r);
}
}
int main(){
while(scanf("%s",s+)!=EOF){
n=strlen(s+);
for(rg int i=;i<=n;i++)
for(rg int j=i;j<=n;j++) f[i][j]=j-i+;
for(rg int l=;l<=n;l++){
for(rg int i=;i+l-<=n;i++){
int j=i+l-;
for(rg int k=i;k<=j;k++){
if(f[i][k]+f[k+][j]<f[i][j]){
f[i][j]=f[i][k]+f[k+][j];
from[i][j]=k;
}
if(check(i,k,j)){
int tmp=f[i][k]++qlen(m);
if(tmp<f[i][j]){
f[i][j]=tmp;
from[i][j]=k;
}
// printf("%d %d %d\n",i,k,j);
}
}
}
}
out(,n);
puts("");
}
// printf("%d\n",f[1][n]);
return ;
}

洛谷 4302 BZOJ 1090 SCOI2003 字符串折叠 UVA1630 Folding(输出方案版)的更多相关文章

  1. BZOJ 1090: [SCOI2003]字符串折叠 区间DP

    1090: [SCOI2003]字符串折叠 Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/p ...

  2. bzoj 1090 [SCOI2003]字符串折叠(区间DP)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1090 [题意] 给定一个字符串,问将字符串折叠后的最小长度. [思路] 设f[i][j ...

  3. BZOJ 1090: [SCOI2003]字符串折叠

    Sol 区间DP. 转移很简单,枚举会形成的断长转移就行,话说上一题我就跟这个是差不多的思路,转移改了改,然后死活过不了... 同样都是SCOI的题...相差4年... Code /********* ...

  4. bzoj 1090: [SCOI2003]字符串折叠【区间dp】

    设f[i][j]为区间(i,j)的最短长度,然后转移的话一个是f[i][j]=min(j-i+1,f[i][k]+f[k+1][j]),还有就是把(k+1,j)合并到(i,k)上,需要判断一下字符串相 ...

  5. 【BZOJ】1090: [SCOI2003]字符串折叠(dp)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1090 随便yy一下.. 设f[i,j]表示i-j的最小长度 f[i, j]=min{j-i+1, f ...

  6. 1090. [SCOI2003]字符串折叠【区间DP】

    Description 折叠的定义如下: 1. 一个字符串可以看成它自身的折叠.记作S  S 2. X(S)是X(X>1)个S连接在一起的串的折叠.记作X(S)  SSSS…S(X个S). ...

  7. BZOJ1090: [SCOI2003]字符串折叠

    区间dp. 一种是分段dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]); 一种是这一段可以缩写dp[i][j]=min(dp[i][j],dp[i][l]+2+ca ...

  8. 【BZOJ1090】[SCOI2003]字符串折叠(动态规划)

    [BZOJ1090][SCOI2003]字符串折叠(动态规划) 题面 BZOJ 洛谷 题解 区间\(dp\).设\(f[i][j]\)表示压缩\([i,j]\)区间的最小长度.显然可以枚举端点转移.再 ...

  9. 洛谷 P3370 【模板】字符串哈希

    洛谷 P3370 [模板]字符串哈希 题目描述 如题,给定N个字符串(第i个字符串长度为Mi,字符串内包含数字.大小写字母,大小写敏感),请求出N个字符串中共有多少个不同的字符串. 友情提醒:如果真的 ...

随机推荐

  1. Vue Router过渡动效

    <router-view> 是基本的动态组件,所以我们可以用 <transition> 组件给它添加一些过渡效果: <transition> <router- ...

  2. 14_传智播客iOS视频教程_OC的数据类型

    对比一下OC和C差别,首先第一个是数据类型. C语言的数据类型分哪几类?C语言有哪些数据类型? 基本数据类型当然还包括int的一些修饰符.像short.long.long long.unsigned. ...

  3. Tomcat的jvm配置

    Tomcat本身不能直接在计算机上运行,需要依赖于操作系统和一个JAVA虚拟机.Tomcat的内存溢出本质就是JVM内存溢出,JAVA程序启动时JVM会分配一个初始内存和最大内存给程序.当程序需要的内 ...

  4. MySQL基础 — 常用命令

    一.连接MySQL 格式: mysql -h主机地址 -u用户名 -p用户密码 1.连接到本机上的MySQ: 首先在打开cmd窗口,输入mysql -uroot -p ,然后空格进入MySQL控制台, ...

  5. base64编码上传图片java后台接收实例

    原文地址:http://blog.csdn.net/tonyfreak/article/details/72522855 思路 前台传以data:image/jpeg;base64,开头的base64 ...

  6. C语言小项目-基于TCP协议和SOCKET编程的网络通信系统

    1.1 功能结构图   网络通信系统一共由4个模块组成,分别是点对点客户端.点对点服务端.服务器中转服务端.服务器中转客户端.这4个模块是成对使用的,点对点客户端和点对点服务端一起使用,服务器中转服务 ...

  7. [HAOI2006]均分数据

    题解 今天下午刚学了模拟退火 借这个题来总结下模拟退火的要注意的问题吧 1 : \(eps\)不要设的太大 2 : 初温\(T\)在2000左右就差不多可以了 3 : 注意题目要求是要求最大值还是最小 ...

  8. Windows环境下使用Netsh命令快速切换IP配置

    不同的内网环境需要使用不同的IP配置,频繁切换令人发狂,因此搜索了快速切换IP配置的方法. Netsh interface IP Set address "以太网" Static ...

  9. Android内存管理(14)*使用开源库LeakCanary检查内存泄漏

    1.简介 它是一个非常简单好用的内存泄漏检测工具库.可以轻松检测Activity,Fragment的内存泄漏.如果有内存泄漏,它会产生一个通知. 2.资料 官网: https://github.com ...

  10. 283 Move Zeroes 移动零

    给定一个数组 nums, 编写一个函数将所有 0 移动到它的末尾,同时保持非零元素的相对顺序.例如, 定义 nums = [0, 1, 0, 3, 12],调用函数之后, nums 应为 [1, 3, ...