UVa 1630 - Folding (区间dp)
作者:互联网
题目链接:https://onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4505
没有看出这是一道区间 \(dp\)
可以将串 \(S\) 分成 \(AB\) 两部分,一种方案是对 \(AB\) 直接拼接,另一种方案是将 \(B\) 折叠进入 \(A\),按照这两种方案转移即可,记录一下转移点用来输出方案
有一些关于字符串 \(string\) 的操作,详见代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 105;
const int INF = 0x3f3f3f3f;
int n;
int dp[maxn][maxn], g[maxn][maxn];
string s;
bool check(int i, int j, int k){
if((j-k) % (k-i+1) != 0) return false;
int mul = (j-k)/(k-i+1);
string t = s.substr(i-1, k-i+1); // 位置从 0 开始
string r = s.substr(k, j-k);
string l;
for(int p = 1 ; p <= mul ; ++p) l += t;
if(l == r) return true;
else return false;
}
int count(int x){
int tmp = x;
int cnt = 0;
while(tmp){
++cnt;
tmp /= 10;
}
return cnt;
}
void print(int i, int j){
if(i == j){
cout << s.substr(i-1, 1);
return;
}
if(g[i][j] < 0){
print(i, -g[i][j]);
print(-g[i][j]+1, j);
} else{
int k = g[i][j];
int mul = (j-k)/(k-i+1); ++mul;
cout << mul << '(';
print(i, k);
cout << ')';
}
}
ll read(){ ll s = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); } while(ch >= '0' && ch <= '9'){ s = s * 10 + ch - '0'; ch = getchar(); } return s * f; }
int main(){
while(cin >> s){
memset(dp, 0x3f, sizeof(dp));
memset(g, 0x3f, sizeof(g));
n = s.length();
for(int i = 1 ; i <= n ; ++i) dp[i][i] = 1;
for(int l = 2 ; l <= n ; ++l){
for(int i = 1 ; i + l - 1 <= n ; ++i){
int j = i + l - 1;
for(int k = i ; k < j ; ++k){
if(dp[i][k] + dp[k+1][j] < dp[i][j]){
dp[i][j] = min(dp[i][j], dp[i][k] + dp[k+1][j]); // 直接拼
g[i][j] = -k;
}
// 折叠
if(check(i, j, k)){
int mul = (j-k)/(k-i+1); mul += 1;
if(count(mul) + 2 + dp[i][k] < dp[i][j]){
dp[i][j] = min(dp[i][j], count(mul) + 2 + dp[i][k]);
g[i][j] = k;
}
}
}
}
}
print(1, n); cout << endl;
}
return 0;
}
标签:1630,ch,Folding,string,int,memset,maxn,UVa,dp 来源: https://www.cnblogs.com/tuchen/p/15080248.html