zoukankan      html  css  js  c++  java
  • poj1239 Increasing Sequences

    题意:用逗号划分数字串,使最后一个子串最小,且开头的子串尽可能大。

    方法:

    两次DP

    1. 求出最后一个子串的值

    状态:从前向后DP,dp[i]代表在0~i的子串中,dp[i]~i所代表的子串是最小的最后子串。

    转移:枚举dp[i]的值由j-1~0,如果dp[i]~i所代表的子串比dp[i-1]~i-1的子串所代表的值大,则dp[i]~i是最小的最后子串。

    2. 求出题目要求的序列

    状态:从后向前DP,dp[i]代表在i~len-1的子串中,i~dp[i]所代表的子串是最大的第一个子串。

    转移:枚举dp[i]的值由i~len-1,如果i~dp[i]所代表的子串比dp[i]+1~dp[dp[i]+1]的子串大,则可增大dp[i]的值选择更大的第一子串。

    以上转自http://blog.csdn.net/cyberzhg/article/details/7538304

    /**
     * Problem:POJ1239
     * Author:Shun Yao
     * Time:2013.5.20
     * Result:Accepted
     * Memo:DP
     */
    
    #include <cstring>
    #include <cstdlib>
    #include <cstdio>
    
    using namespace std;
    
    const long Maxn = 88;
    
    long n, N, minl[Maxn], maxl[Maxn];
    char s[Maxn];
    
    long compare(char *s1, char *e1, char *s2, char *e2) {
    	while (*s1 == '0' && s1 != e1)
    		++s1;
    	while (*s2 == '0' && s2 != e2)
    		++s2;
    	static long l1, l2;
    	l1 = e1 - s1;
    	l2 = e2 - s2;
    	if (l1 != l2)
    		return l1 - l2;
    	while (s1 != e1) {
    		if (*s1 != *s2)
    			return *s1 - *s2;
    		++s1;
    		++s2;
    	}
    	return 0;
    }
    
    int main() {
    	static long i, j;
    	freopen("poj1239.in", "r", stdin);
    	freopen("poj1239.out", "w", stdout);
    	while(scanf(" %s", s), strcmp(s, "0")) {
    		n = strlen(s);
    		memset(minl, 0, sizeof minl);
    		for (i = 1; i < n; ++i)
    			for (j = i - 1; j >= 0; --j)
    				if (compare(s + minl[j], s + j + 1, s + j + 1, s + i + 1) < 0) {
    					minl[i] = j + 1;
    					break;
    				}
    		memset(maxl, 0, sizeof maxl);
    		N = minl[n - 1];
    		maxl[N] = n - 1;
    		for (i = N - 1; i >= 0 && s[i] == '0'; --i)
    			maxl[i] = n - 1;
    		for (; i >= 0; --i)
    			for (j = N - 1; j >= i; --j)
    				if (compare(s + i, s + j + 1, s + j + 1, s + maxl[j + 1] + 1) < 0) {
    					maxl[i] = j;
    					break;
    				}
    		for (i = 0, j = maxl[i]; i < n; j = maxl[j + 1]) {
    			if (i)
    				putchar(',');
    			while (i < n && i <= j)
    				printf("%c", s[i++]);
    		}
    		putchar('\n');
    	}
    	fclose(stdin);
    	fclose(stdout);
    	return 0;
    }
    


    作者:HSUPPR
    出处:http://www.cnblogs.com/hsuppr/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出 原文链接,否则保留追究法律责任的权利。

  • 相关阅读:
    git rebase解决合并冲突
    Google GMS介绍
    MTK Android修改System分区
    Adb adb push (remote write failed: No space left on device)
    Android Visibility控件显示和隐藏
    MTK Android中设置默认时区
    初级Oracle和SQL学习者的学习笔记。韩顺平-玩转oracle。
    网络知识从零开始一:私有地址。
    oracle中有关用户、角色的一些概念。
    oracle中的一些函数笔记
  • 原文地址:https://www.cnblogs.com/hsuppr/p/3088320.html
Copyright © 2011-2022 走看看