HDU2067小兔的棋盘

小兔的棋盘

Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 8981    Accepted Submission(s): 4662


Problem Description
小兔的叔叔从外面旅游回来给她带来了一个礼物,小兔高兴地跑回自己的房间,拆开一看是一个棋盘,小兔有所失望。不过没过几天发现了棋盘的好玩之处。从起点(0,0)走到终点(n,n)的最短路径数是C(2n,n),现在小兔又想如果不穿越对角线(但可接触对角线上的格点),这样的路径数有多少?小兔想了很长时间都没想出来,现在想请你帮助小兔解决这个问题,对于你来说应该不难吧!
 

Input
每次输入一个数n(1<=n<=35),当n等于-1时结束输入。
 

Output
对于每个输入数据输出路径数,具体格式看Sample。
 

Sample Input

1 3 12 -1
 

Sample Output

1 1 2 2 3 10 3 12 416024
 

思路:


我们只考虑下三角的情况,然后总数只要乘2即可。

那么我们不难得出,假设我们要走到(i,j)那么我们只能从(i-1,j)向右走或者从(i,j-1)向上走。

那么我们用dp[i][j]表示从(0,0)走到(i,j)且不超越对角线的情况数(仅考虑下三角)。

那么dp[i][j] = dp[i-1][j] + dp[i][j-1]

我们打表一下就可以了.

#include
#define fur(i,a,b) for(int i=(a);i<=(b);i++)
#define cl(a) memset((a),0,sizeof(a))
using namespace std;
typedef long long ll;
inline void gn(long long&x){
    int sg=1;char c;while(((c=getchar())<'0'||c>'9')&&c!='-');c=='-'?(sg=-1,x=0):(x=c-'0');
    while((c=getchar())>='0'&&c<='9')x=x*10+c-'0';x*=sg;
}
inline void gn(int&x){long long t;gn(t);x=t;}
// (づ°ω°)づe★
ll dp[40][40];
void init(){
	cl(dp);
	dp[0][0] = 1;
	fur(i,1,35){
		fur(j,0,i){
			dp[i][j] = dp[i-1][j] + dp[i][j-1];
		}
	}
	
}
int main(){
	//freopen("E:\\data.in","r",stdin);
	//freopen("E:\\data.out","w",stdout);
	int kase = 0;
	init();
	while(1){
		int t;
		gn(t);
		if(t == -1) return 0;
		printf("%d %d %lld\n",++kase,t,dp[t][t]*2ll);
	}
	return 0;
}


你可能感兴趣的:(动态规划,数论)