POJ1239 dp (严格递增子序列)

来源:互联网 发布:淘宝二手市场网 编辑:程序博客网 时间:2024/06/06 12:27

字符串的前缀后缀处理,严格递增子序列

题意:

题目要求在整个是递增子序列的前提下最后一个元素的值要最小,并且在此前提下第一个的值要最大.

思路:

很奇怪的问题,但是细细想来就是要求我们找到严格递增的的序列,可是有两个限制,我们知道如果dp[i]定义为从第i个之前的dp[i]个数字组成的数字满足递增,这种定义方式必然导致从前往后遍历,这会导致每一个递增的数列都是尽可能的小。如此一来,其实就已经得到了最小的最后一个数字,那么我们再从后往前遍历就会得到想要的答案。

第二次dp[i] 表示的是从第i个数字开始往后的dp[i]个数字组成的数字满足严格递增的条件。

那么问提示如何dp呢?

对于第一次,根据其定义的意义,就从第 i 个数字开始,我们逐次增加长度,找打满足条件的就break

对于第二次,根据其定义的意义,若想得到比较大的数字,就从大的区间开始找。

  • 比较需要注意的是:题目不要求输出最长的,只要求输出满足连个条件的。
  • 此题很好的是考验到了,对dp 的定义,是从哪里开始切入的
#include <iostream>#include <cstdio>#include <cstring>using namespace std;const int maxn = 100;int dp[maxn];char s[maxn];int judge(int x1,int y1,int x2,int y2){    while(s[x1] == '0' && x1 <= y1) x1++;    while(s[x2] == '0' && x2 <= y2) x2++;    if(x1 > y1) return false;    if(x2 > y2) return true;    if(y1 - x1 > y2 - x2) return true;    else if(y2 - x2 > y1 - x1) return false;    else {        while(x1 <= y1) {            if(s[x1] > s[x2]) return true;            else if(s[x2] > s[x1]) return false;            x1++,x2++;        }    }    return false;}int main(int argc, char const *argv[]){    freopen("in.txt","r",stdin);    while(scanf("%s",s+1) != EOF) {        int len = strlen(s+1);        if(s[1] == '0' && len == 1) break;        memset(dp,0,sizeof(dp));        dp[1] = 1;        for (int i = 2; i <= len; ++i) {            dp[i] = i;            for(int j = i - 1;j >= 1; j--) {                if(judge(j+1,i,j-dp[j]+1,j)) {                    dp[i] = i - j;                    break;                }            }        }        int lsatNumberStart = len - dp[len] + 1;        dp[lsatNumberStart] = dp[len];        for(int i = lsatNumberStart-1;i >= 1; i--) {            if(s[i] == '0') {                dp[i] = dp[i+1] + 1;                continue;            }            for(int j = lsatNumberStart;j >= 1; j--) {                if(judge(j,j+dp[j]-1,i,j-1)) {                    dp[i] = j - i;                    break;                }            }        }        for(int i = 1;i <= dp[1]; i++) {            printf("%c",s[i]);        }        int t = dp[1] + 1;        while(t <= len) {            printf(",");            for(int i = t;i < t + dp[t]; i++)                printf("%c",s[i]);            t = t + dp[t];        }        printf("\n");    }    return 0;}