poj-1221

#include <stdio.h>

unsigned long UnimodalNum[1000][1000] = {0};

void init() {
    for(int i = 0; i <1000; i++) {
        for (int j = 999; j >= 0; j--) {
            if (i == 0) { // N is 0.
                UnimodalNum[i][j] = 1;    // N is 0, means no change any more, so only 1 combination.
            } else if (j == 0) { // start from 0.
                UnimodalNum[i][j] = -1;
            } else if (i < j) {
                UnimodalNum[i][j] = -1;
            } else if (i == j) {
                UnimodalNum[i][j] = 1;
            } else {
                UnimodalNum[i][j] = -1;

                long uniNum = 0;
                long begin = j-1;
                while (1) {
                    // printf("%d\n", begin);
                    begin++;
                    if (begin >= (i/2 + 1)) {
                        break;
                    } else if (begin*2 == i) {
                        uniNum += 1;
                    } else if (i - begin*2 < begin) {
                        continue;
                    } else {
                        if (UnimodalNum[i - 2*begin][begin] == -1) {
                            uniNum += 1;
                        } else {
                            uniNum += UnimodalNum[i - 2*begin][begin];
                        }
                    }
                }
                UnimodalNum[i][j] = uniNum + 1;
            }
        }
    }
}

int main() {
    int num;
    init();
    while(1) {
        scanf("%d", &num);
        if (num == 0) {
            return 0;
        }
        printf("%d %lu\n", num, UnimodalNum[num][1]);
    }
}


DP, 最优解这里变成了遍历所有可能组合的总数(和一般的有点小不一样)

题最大的输入 是 231,

所以维护一个232的二维矩阵就够了。

还有一点就是 全部用long(包括中间数据), 不然220以后就溢出了。

着了的 unimodlNum[i][j]的含义是:

总数N为i, 从j开始进行回文不递减排列的组合的个数。

极限情况:

i == 0, 没有意义, 设为 -1.

i == j, 只有一种排列方式.

i < j, 这种情况根本没有排列, 无解, 设 -1;。

j == 0, 也没啥意义, 设为 -1;

一般情况:

从j开始遍历(设遍历变量为begin),在(j每次递增)

当j == 2*i时,组合个数+1           (i, i)

当  j >= i/2+1时,后面已经不再可能有解, 跳出循环.

当 j - 2i < i时, 此组合不是解,但是不能跳出循环, 继续后面(后面还可能有解, 这种情况下不可能在有 (j, ....., j)的组合, 但还可能有(j,j)的组合)

其他的 则是 组合个数 +  unimodlNum[i - 2*begin][begin],

再分为: 如果 unimodlNum[i - 2*begin][begin],是一个无效解, 那么组合个数加1(及 (j....j)的组合不可能存在, 但是可以由(j,i-2j,j)的组合)

     否则 组合个数+unimodlNum[i - 2*begin][begin]。


这些题深感 主要难处是要去想清楚所有的边边角角.




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值