dp较水题,只要整数划分dp情况了,那么此题就可以瞬间AC了。
大致题意:先给定一个整数串,若该整数串为回文串,且为单峰回文串(即从开头非严格递增到中间,然后从中间非严格递减到结尾),且所有个数的和为n,则为整数n的一个单峰回文串,先要求给出n的值,输出所有整数n的单峰回文串个数。
本题需要注意的是分情况讨论:
1)奇数情况
则减少到1为止
2)偶数情况
则减少到2为止,然后就是整数n/2的划分了,代码中有详细注释。整数划分在上一篇博客中有详细说明,这里不再重叙。
直接看代码: 728K+0MS
#include <stdio.h>
#include <stdlib.h>
#define Max 300 //预打表250*250的整数划分组合数
__int64 dp[Max][Max]; // 记录整数划分组合数
__int64 Sum; // 记录最后的个数
int n;
void Dp(int n,int m){ // 整数划分组合数dp
int i,j;
for(i=1;i<=n;i++)
dp[i][1]=1;
for(i=1;i<=m;i++)
dp[1][i]=1;
for(i=2;i<=n;i++)
for(j=2;j<=m;j++){
if(i<=j)
dp[i][j]=dp[i][i-1]+1;
else
dp[i][j]=dp[i][j-1]+dp[i-j][j];
}
}
int main(){
Dp(250,250); // 预打表
while(scanf("%d",&n),n){
printf("%d ",n);
Sum=1; // 初始化为1,表示数本身的情况
if(n&1){ // 若为奇数
int inc=1;
while(n>1){ // 每次减少2,组合数要加上dp[inc][n],即以减少的数的一半为n,在不超过剩余数的范围内选择数组合成n的不同组合个数,直到剩余数为1为止
n-=2;
Sum+=dp[inc][n];
//printf("%d %d==%I64d \n",inc,n,dp[inc][n]);
inc++;
}
}
else{
int temp=n;
int inc=1; // 同上原理,只是这里跳出条件为n>2,因为下一次的组合数为dp[n/2][n/2],即原数的一半
while(n>2){
n-=2;
Sum+=dp[inc][n];
inc++;
}
Sum+=dp[temp/2][temp/2];
}
printf("%I64d\n",Sum); //输出总个数
}
return 0;
}