zoukankan      html  css  js  c++  java
  • BZOJ 1090

    Magic Door

    题目大意:

    给一个字符串,可以将重复的串缩成x(a),表示x个a,求能缩成的最小长度。

    题目分析

    区间dp: dp[i][j]表示i~j处理后的最小长度, 则有

    [dp[i][j] = min{dp[i][k] + dp[k + 1][j] (i <= k < j)} ]

    并且如果i~j能够拆成若干个重复串的话:

    [dp[i][j] = min{dp[i][k] + 2 + num((j - i + 1) / len)} ]

    len表示重复串的长度,枚举断点更新即可。
    我比较喜欢写记忆搜索。

    code

    #include<bits/stdc++.h>
    using namespace std;
    
    const int N = 105;
    int dp[N][N], len;
    char s[N];
    
    inline int num(int x){
    	int ret = 0;
    	while(x) x /= 10, ret++;
    	return ret;
    }
    
    inline bool check(int l, int r, int k){
    	if((r - l + 1) % (k - l + 1)) return false;
    	int ll = k - l + 1, tmp = (r - l + 1) / ll;
    	for(int i = 2; i <= tmp; i++)
    		for(int j = 1; j <= ll; j++)
    			if(s[l + (i - 1) * ll + j - 1] != s[l + (i - 2) * ll + j - 1]) return false;
    	return true;
    }
    
    inline int DP(int l, int r){
    	if(dp[l][r] != -1) return dp[l][r];
    	int tmp = r - l + 1;
    	for(int k = l; k < r; k++) tmp = min(tmp, DP(l, k) + DP(k + 1, r));
    	for(int k = l; k < r; k++)
    		if(check(l, r, k)) tmp = min(tmp, DP(l, k) + 2 + num((r - l + 1) / (k - l + 1)));
    	return dp[l][r] = tmp;
    }
    
    int main(){
    	ios::sync_with_stdio(false);
    	cin.tie(NULL), cout.tie(NULL);
    	cin >> s + 1;
    	len = strlen(s + 1);
    	memset(dp, -1, sizeof dp);
    	cout << DP(1, len);
    }
    
  • 相关阅读:
    chrome、firefox、IE中input输入光标位置错位解决方案
    IE兼容opacity
    Linux下redis5的安装及伪分布式集群搭建
    Linux文件编辑命令详细整理
    saltstack
    redis集群
    系统调优
    centos7 telnet 登录升级ssh
    keepalive简单高可用 ha
    docker
  • 原文地址:https://www.cnblogs.com/CzYoL/p/7636181.html
Copyright © 2011-2022 走看看