没有原题。。。
囧。。
[问题描述]
游戏规则是这样,有n(1<=n<=100)行格子,第一行由n个格子,第二行有n-1个格子,第三行由n-2个格子,……以此类推,第n行有1个格子。要求再这些格子上摆放棋子。摆放的时候要注意,每一个格子只能放一个棋子。同一行的格子摆放必须遵守从左至右的顺序,在一行内从左至右摆放时不能跳过某个格子来摆放。每一行放的棋子数不能超过上一行的棋子数。
输入文件(diagrams.in):仅1行,一个正整数n。
输出文件(diagrams.out):仅1行,方案总数。
样例:输入2,输出4。
(样例补充说明:不能一个棋子都不放)
。。
这题DP好吧,裸的DP题。
不过要特判一下如果输入1要输出1.
设f[i][j]表示放到第[i]行,前j列都放了棋子的方案数
很明显就可以得出状态转移方程。。
f[i][j]=sum(f[i-1][k])(j<i,k<=j)
f[i][i]=f[i][i-1];
然后以为很简单,就交了。
发现数据范围一只。
n<=100,好小啊。。
但是。。
n到30就爆long long了。
怎么办。
写了个高精度。。
终于过了233~
高精度不能写炸诶~
下面贴代码
#include<iostream> #include<cstdio> #include<cstring> using namespace std; char f[101][101][101]; int n; void add(char a[],char b[]) { int l; int l1=strlen(a); int l2=strlen(b); int num1[101],num2[101]; memset(num1,0,sizeof(num1)); memset(num2,0,sizeof(num2)); for(int i=0;i<=l1-1;i++) num1[l1-1-i]=a[i]-'0'; for(int i=0;i<=l2-1;i++) num2[l2-1-i]=b[i]-'0'; if(l1>l2)l=l1; else l=l2; for(int i=0;i<=l-1;i++) { num1[i]+=num2[i]; if(num1[i]>=10)num1[i+1]++,num1[i]-=10; } if(num1[l]!=0)l++; for(int i=l-1;i>=0;i--) a[l-1-i]=num1[i]+48; } void work(int x){ if(x==1){printf("1 ");return;} else { f[1][1][0]='1'; f[1][0][0]='1'; for(int i=2;i<=n;i++) { for(int j=0;j<i;j++) { for(int k=0;k<=j&&(k<=(i-1));k++) { if(strcmp(f[i][j],"")==0)f[i][j][0]='0'; add(f[i][j],f[i-1][k]); } } for(int j=0;j<strlen(f[i][i-1]);j++) f[i][i][j]=f[i][i-1][j]; } char ans[101]=""; ans[0]='0'; for(int i=1;i<=n;i++) { add(ans,f[n][i]); } printf("%s",ans); } } int main(){ freopen("diagrams.in","r",stdin); freopen("diagrams.out","w",stdout); scanf("%d",&n); work(n); fclose(stdin); fclose(stdout); }