未名湖的烦恼-回溯,动态规划

问题描述 
  每年冬天,北大未名湖上都是滑冰的好地方。北大体育组准备了许多冰鞋,可是人太多了,每天下午收工后,常常一双冰鞋都不剩。 
  每天早上,租鞋窗口都会排起长龙,假设有还鞋的m个,有需要租鞋的n个。现在的问题是,这些人有多少种排法,可以避免出现体育组没有冰鞋可租的尴尬场面。(两个同样需求的人(比如都是租鞋或都是还鞋)交换位置是同一种排法) 
输入格式 
  两个整数,表示m和n 
输出格式 
  一个整数,表示队伍的排法的方案数。 
样例输入 
3 2 
样例输出 

数据规模和约定 
  m,n∈[0,18] 
 
题解 回溯:构造一个二叉树,得到排列完所有人的情况,结果++,最后输出结果。
样例输入中的3 2,会产生下面的树,没有画图工具大家凑合一下。其中1代表送鞋的,0代表租鞋的。
 
 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<stdlib.h>
 4 int now=0;//当前冰鞋
 5 int res;//人数
 6 int k=0;
 7 void rank(int m,int n){
 8     if(m==0&&n==0)
 9         res++;
10     if(now>0){
11         if(n>0)
12             --now,rank(m,n-1),now++;    //回溯
13         if(m>0)
14             ++now,rank(m-1,n),now--;
15     }else
16         if(m>0)
17             ++now,rank(m-1,n),now--;
18 }
19 
20 int main(){
21     int m,n;
22     freopen("a.txt","r",stdin);
23     scanf("%d %d",&m,&n);
24     if(m<n){
25         printf("%d",0);return 0;}
26     if(n==0){
27         printf("%d",1);return 0;}
28     rank(m,n);
29     printf("%d",res);
30     return 0;
31 }
题解 动态规划:
当i=j时,dp[i][j]=dp[i][j-1] 
当i>j时,当前位置随便放借鞋还是还鞋都可以, dp[i][j]=dp[i-1][j-1]+dp[i][j-1]
 1 #include<iostream>
 2 #include<stdio.h>
 3 #include<stdlib.h>
 4 #include<string.h>
 5 using namespace std;
 6 int dp[25][25];
 7 int main()
 8 {
 9     int m, n;
10     scanf("%d%d",&m,&n);
11     memset(dp,0,sizeof(dp));
12     for (int i = 1; i <= m; i++){
13         dp[i][0] = 1;
14     }
15     for (int i = 1; i <= m; i++){
16         for (int j = 1; j <= n; j++){
17             if (i == j){
18                 dp[i][j] = dp[i][j - 1];
19             }
20             if (i>j){
21                 dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
22             }
23         }
24     }
25     printf("%d\n",dp[m][n]);
26     return 0;
27 }

今天在这道题上浪费了不少时间,所以记录一下。

posted @ 2018-03-11 17:34  _春华秋实  阅读(169)  评论(0)    收藏  举报