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

29 篇文章 0 订阅
2 篇文章 0 订阅

小兔的棋盘

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


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



思路:
       简单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;
}
     
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值