• 周一. 8月 15th, 2022

5G编程聚合网

5G时代下一个聚合的编程学习网

热门标签

UVa 1630

admin

11月 28, 2021

题目链接: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;
}

发表回复

您的电子邮箱地址不会被公开。