poj 1221 UNIMODAL PALINDROMIC DECOMPOSITIONS 動態規劃

UNIMODAL PALINDROMIC DECOMPOSITIONS
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 2580   Accepted: 1200

Description

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

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

Output

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.

Sample Input

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

Sample Output

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
題解只寫給新手看,大牛略過。
最近一直在作動態規劃的題,但這道還是想了好久,水啊。
先研究一下每一組數據時怎樣由前面的推出的。
比如 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個。
將6拆成兩個相同的數和另一個大於這個數的數或者0(真拗口)。直接看下面就好:
1、6=1+1+4。那麼他可以將4的所有情況兩邊都加1變成6的解 (1 4 1), (1 1 2 1 1), (1 2 2 1), ( 1 1 1 1 1 1)共4個。
2、6=2+2+2。那麼他可以將2的所有最小值大於等於2的情況兩邊加2 即將(2) 變成 (2,2,2) 共1個
3、6=3+3+0。注意只有另一個數是0的時候纔可以這麼拆 如 5= 2+2+1 是不可以的。那麼他可以將0 的所有情況兩邊加3,變成3,3 共1個。這裏默認0的情況總數是1.
4、6本身自己 (6) 就是一組 共1個
所以 6的解共4+1+1+1=7個。
由以上分析得到狀態轉移方程 s[i][j] = s[i-2*j][j] + s[i][j+1];(1<=j<=i/2)
其中i表示數據的和,就是題中的n,j表示i的所有解中所有數大於等於j的情況總數(之所以這樣定義可以參考上面分析中的第2步)
具體實現
1、將s[i][j] (i>=j>i/2) 內容預處理成1(因爲對於j>i/2時 所有的s[i][j]都是1,如s[6][4]=s[6][5]=s[6][6]=1 只有(6)一個)。
2、將s[i][j] (i<j) 內容預處理成0 (因爲根據定義j不可能比i大。)
3、將s[0][j]  內容預處理成1 (因爲當需要調用s[0][j]時表示一個數拆成了完全相同的兩個數,結果當然是一個了,)
4、在for (i=2;i<=nax;i++)的每次循環中加入for (j=i/2;j>=1;j--)循環,每次逆推結果
程序實現過程
比如i=6時
1、j=3 s[6][3] = s[6-3*2][3] + s[6][4] = 1 + 1 =2 ; 表示6中解大於3的有兩種(3,3) (6);
2、j=2 s[6][2] = s[2][2] + s[6][3] = 1 + 2 =3;
3、j=1 s[6][1] = s[4][1] + s[6][2] = 4 + 3 =7;  s[6][1]中儲存n=6時的所有解
。。。。
具體代碼
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
__int64 s[301][301];
int n;
int main()
{
int i,j,t;
memset(s,0,sizeof(0));
for (i=1;i<=300;i++)
   for (j=i;j>=0;j--)
      s[i][j] = 1;
for (i=0;i<=300;i++) s[0][i]=1;
for (i=2;i<=300;i++)
   for (j=i/2;j>=1;j--)
     {
     s[i][j] = s[i-2*j][j] + s[i][j+1];
     }
while (scanf("%d", &n), n!=0)
{
   printf("%d %I64d/n", n, s[n][1]);
}
}
 
細節:s的內容可能超出int的範圍需要用int64纔可以ac
發佈了31 篇原創文章 · 獲贊 0 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章