您的位置:首页 > 编程语言 > C语言/C++

2067 小兔的棋盘【dp】【记忆化搜索dfs】

2016-12-01 17:32 447 查看

小兔的棋盘

Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 6193 Accepted Submission(s): 3373


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

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

[align=left]Output[/align]
对于每个输入数据输出路径数,具体格式看Sample。

[align=left]Sample Input[/align]

1
3
12
-1

[align=left]Sample Output[/align]

1 1 2
2 3 10
3 12 416024



思路:

       简单dp, 因为是求最短,所以当前状态只能由上面或者左面过来(上半部分三角形),由于不能过对角线,我们可以只求一半,也就是上面三角形,最后乘2就行了,直接dp打表,或者记忆化搜索,对于记忆化搜索也可以1边记忆化搜索打表,就是最后在转换矩阵,终点变成了起点,起点变终点什么的,不难,我下面的是dp打表,和直接记忆化搜索的代码,记忆化搜索打表的没写,想写的直接在记忆或搜索的那个改改就行了。


dp

#include<stdio.h>
#include<string.h>

__int64 dp[40][40] = {0};

void solve(int n)
{
dp[1][1] = 1;
for(int i = 1 ;i <= n ;i ++)
for(int j = i ;j <= n ;j ++)
{
if(i == 1 && j == 1) continue;
dp[i][j] = dp[i][j-1] + dp[i-1][j];
}
}

int main ()
{
int n ,cas = 1;
solve(36);
while(~scanf("%d" ,&n) && n != -1)
{
printf("%d %d %I64d\n" ,cas ++ ,n ,dp[n+1][n+1] * 2);
}
return 0;
}


记忆化搜索

#include<stdio.h>
#include<string.h>

int mark[40][40];
__int64 dp[40][40];
int n;

__int64 DFS(int x ,int y)
{
if(x == n + 1 && y == n + 1) return 1;
if(mark[x][y]) return dp[x][y];
__int64 sum = 0;
if(x + 1 <= n + 1 && x + 1 <= y)
sum += DFS(x + 1 ,y);
if(y + 1 <= n + 1)
sum += DFS(x ,y + 1);
mark[x][y] = 1;
dp[x][y] = sum;
return sum;
}

int main ()
{
memset(mark ,0 ,sizeof(mark));
int cas = 1;
while(scanf("%d" ,&n) && n != -1)
{
memset(mark ,0 ,sizeof(mark));
printf("%d %d %I64d\n" ,cas ++ ,n ,DFS(1 ,1) * 2);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  c语言 vc 6 杭电 递归