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/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出
原文链接,否则保留追究法律责任的权利。

浙公网安备 33010602011771号