• UVa 1630


    题目链接: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;
    }
    
  • 相关阅读:
    vmware克隆Centos6.4虚拟机网卡无法启动问题
    mysql错误:Statement violates GTID consistency
    /etc/vsftpd.conf详解
    Linux /etc/fstab文件
    sudo命令详解
    linux fack 文件系统修复命令
    ORA-01502: 索引或这类索引的分区处于不可用状态
    Oracle 完整性约束错误
    linux下部署redis
    Python 发送邮件案例
  • 原文地址:https://www.cnblogs.com/tuchen/p/15080248.html
Copyright © 2020-2023  润新知