* 动态规划(2) 编程题#1:UNIMODAL PALINDROMIC DECOMPOSITIONS(梯形数组 *R[N] 省空间,while (cin >> N){,long long型数组)

本文介绍了一种针对整数N的单峰回文分解问题的算法实现,通过动态规划方法计算所有可能的单峰回文序列,并给出了详细的程序代码及运行示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

编程题#1:UNIMODAL PALINDROMIC DECOMPOSITIONS

来源: POJ (http://bailian.openjudge.cn/practice/1221/)

注意: 总时间限制: 1000ms 内存限制: 65536kB

描述
A sequence of positive integers is Palindromic if it reads the same forward and backward. For example:
23 11 15 1 37 37 1 15 11 23
1 1 2 3 4 7 7 10 7 7 4 3 2 1 1
A Palindromic sequence is Unimodal Palindromic if the values do not decrease up to the middle value and then (since the sequence is palindromic) do not increase from the middle to the end For example, the first example sequence above is NOT Unimodal Palindromic while the second example is.

A Unimodal Palindromic sequence is a Unimodal Palindromic Decomposition of an integer N, if the sum of the integers in the sequence is N. For example, all of the Unimodal Palindromic Decompositions of the first few integers are given below:
1: (1)
2: (2), (1 1)
3: (3), (1 1 1)
4: (4), (1 2 1), (2 2), (1 1 1 1)
5: (5), (1 3 1), (1 1 1 1 1)
6: (6), (1 4 1), (2 2 2), (1 1 2 1 1), (3 3),(1 2 2 1), ( 1 1 1 1 1 1)
7: (7), (1 5 1), (2 3 2), (1 1 3 1 1), (1 1 1 1 1 1 1)
8: (8), (1 6 1), (2 4 2), (1 1 4 1 1), (1 2 2 2 1),(1 1 1 2 1 1 1), ( 4 4), (1 3 3 1), (2 2 2 2),(1 1 2 2 1 1), (1 1 1 1 1 1 1 1)

Write a program, which computes the number of Unimodal Palindromic Decompositions of an integer.

输入
Input consists of a sequence of positive integers, one per line ending with a 0 (zero) indicating the end.

输出
For each input value except the last, the output is a line containing the input value followed by a space, then the number of Unimodal Palindromic Decompositions of the input value. See the example on the next page.

样例输入

2
3
4
5
6
7
8
10
23
24
131
213
92
0

样例输出

2 2
3 2
4 4
5 3
6 7
7 5
8 11
10 17
23 104
24 199
131 5010688
213 1055852590
92 331143

提示
N < 250

解题思路参考:
http://blog.sina.com.cn/s/blog_7223fd910100x2bw.html

注:
求解最后的结果只需要枚举一下回文序列中间的数字就可以了(递推的终止条件!!!);偶数有两个,奇数只有一个。
用long long型数据

程序解答:

#include<iostream>  
#include<cstring>  
using namespace std;

//全局变量 R[251][251],动态规划的精髓!
long long R[251][251];   //记录数字N的以不小于m开头的单峰回文串数

int main(){
    int N;
    memset(R, 0, sizeof(R));
    //cout << "当N最大取12时,以下依次输出 i " << "j " << "i-2*j " << "k " << ": " << "R[i][j]" << endl;
    for (int i = 1; i <= 250; ++i){
        //cout << endl;
        R[i][i] = 1;          //数字n以n开头则只有一种情况,如 6: (6);也是递推的终止条件!!!
        if (i % 2 == 0)
            R[i][i / 2] = 1;  //偶数n以n/2开头则也只有一种情况,如 6: (3 3);也是递推的终止条件!!!
        for (int j = 1; i - 2 * j >= j; ++j){  //此处k要从j处开始循环!
            //此处i>=3时,j才能开始循环!
            for (int k = j; i - 2 * j >= k; ++k){
                R[i][j] += R[i - 2 * j][k];
                //cout << "i:" << i << " " << "j:" << j << " " << "i-2*j:" << i - 2 * j << " " << "k:" << k << " :: " << R[i][j] << "   ";
                //cout << i << " " << j << " " << i - 2 * j << " " << k << " : " << R[i][j] << "   ";
            }
            //cout << endl;
        }
    }

    while (cin >> N){
        if (N == 0)
            break;
        long long sum = 0;  // sum也得是 long long 型!
        for (int i = 1; i <= N; ++i)
            sum += R[N][i];
        cout << N << " " << sum << endl;
    }

    return 0;
}

其它解法参考:
http://blog.youkuaiyun.com/kindlucy/article/details/7434771



节省空间技巧(定义梯形数组 *R[N] 省空间):

long long *R[N]; 
for (int i = 0; i< N; i++){
    R[i] = new long long[i + 1];
    for (int j = 0; j <= i; j++){
        R[i][j] = 0;
    }
}



程序内部动态变化分析

当N最大取12时的内部变化举例:
比如R[8][1]=R[6][1]=R[4][1]=R[2][1]=1, R[2][1]是递推终止条件!!!
比如R[9][2]=R[5][4]=0, R[5][4]是递推终止条件!!!
比如R[9][2]=R[5][5]=1, R[5][5]是递推终止条件!!!

当N最大取12时,以下依次输出 i j i-2*j k : R[i][j]

3 1 1 1 : 1

4 1 2 1 : 1 4 1 2 2 : 2

5 1 3 1 : 1 5 1 3 2 : 1 5 1 3 3 : 2

6 1 4 1 : 2 6 1 4 2 : 3 6 1 4 3 : 3 6 1 4 4 : 4
6 2 2 2 : 1

7 1 5 1 : 2 7 1 5 2 : 2 7 1 5 3 : 2 7 1 5 4 : 2 7 1 5 5 : 3
7 2 3 2 : 0 7 2 3 3 : 1

8 1 6 1 : 4 8 1 6 2 : 5 8 1 6 3 : 6 8 1 6 4 : 6 8 1 6 5 : 6 8 1 6 6 : 7
8 2 4 2 : 1 8 2 4 3 : 1 8 2 4 4 : 2

9 1 7 1 : 3 9 1 7 2 : 4 9 1 7 3 : 4 9 1 7 4 : 4 9 1 7 5 : 4 9 1 7 6 : 4 9 1 7 7 : 5
9 2 5 2 : 0 9 2 5 3 : 0 9 2 5 4 : 0 9 2 5 5 : 1
9 3 3 3 : 1

10 1 8 1 : 7 10 1 8 2 : 9 10 1 8 3 : 9 10 1 8 4 : 10 10 1 8 5 : 10 10 1 8 6 : 10 10 1 8 7 : 10 10 1 8 8 : 11
10 2 6 2 : 1 10 2 6 3 : 2 10 2 6 4 : 2 10 2 6 5 : 2 10 2 6 6 : 3
10 3 4 3 : 0 10 3 4 4 : 1

11 1 9 1 : 5 11 1 9 2 : 6 11 1 9 3 : 7 11 1 9 4 : 7 11 1 9 5 : 7 11 1 9 6 : 7 11 1 9 7 : 7 11 1 9 8 : 7 11 1 9 9 : 8
11 2 7 2 : 1 11 2 7 3 : 1 11 2 7 4 : 1 11 2 7 5 : 1 11 2 7 6 : 1 11 2 7 7 : 2
11 3 5 3 : 0 11 3 5 4 : 0 11 3 5 5 : 1

12 1 10 1 : 11 12 1 10 2 : 14 12 1 10 3 : 15 12 1 10 4 : 15 12 1 10 5 : 16 12 1 10 6 : 16 12 1 10 7 : 16 12 1 10 8 : 16 12 1 10 9 : 16 12 1 10 10 : 17
12 2 8 2 : 2 12 2 8 3 : 2 12 2 8 4 : 3 12 2 8 5 : 3 12 2 8 6 : 3 12 2 8 7 : 3 12 2 8 8 : 4
12 3 6 3 : 1 12 3 6 4 : 1 12 3 6 5 : 1 12 3 6 6 : 2
12 4 4 4 : 1

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值