赛码网编程练习(六)

击鼓传花

题目描述 

学校联欢晚会的时候,为了使每一个同学都能参与进来,主持人常常会带着同学们玩击鼓传花的游戏。游戏规则是这样的:n个同学坐着围成一个圆圈,指定一个同学手里拿着一束花,主持人在旁边背对着大家开始击鼓,鼓声开始之后拿着花的同学开始传花,每个同学都可以把花传给自己左右的两个同学中的一个(左右任意),当主持人停止击鼓时,传花停止,此时,正拿着花没传出去的那个同学就要给大家表演一个节目。
聪明的小明提出一个有趣的问题:有多少种不同的方法可以使得从小明手里开始传的花,传了m次以后,又回到小明手里。对于传递的方法当且仅当这两种方法中,接到花的同学按接球顺序组成的序列是不同的,才视作两种传花的方法不同。比如有3个同学1号、2号、3号,并假设小明为1号,花传了3次回到小明手里的方式有1->2->3->1和1->3->2->1,共2种。

输入:

输入共一行,有两个用空格隔开的整数n,m(3<=n<=30,1<=m<=30)

输出:

 

输出共一行,有一个整数,表示符合题意的方法数

 

样例输入

 

 

3 3

样例输出

 

2

 

解题思路:这个题最开始自己想错了,以为仅仅是从n个数中取出m个数的排列,但是没考虑到m>n时的情况,整个数据相当于一个循环数组,每个数能够向左或向右走,这个题用到了dp或dfs的思想,这个自己好久没做这方面的题,感觉有些生疏,决定好好复习一下相关知识再来解决这个题,现在的思路是受大神启发的。等我理顺了思路再来发自己的代码。想知道答案的同学可以自行百度。

 

 

#include<stdio.h>
#include<string.h>
#include<assert.h>
#include<math.h>
#include<string>
#include<iostream>
#include<algorithm>
#pragma warning(disable:4996)
using namespace std;

void fre()
//输出重定向
{
    freopen("E:\\input.txt", "r", stdin);
    freopen("E:\\output.txt", "w", stdout);
}


int n, m;
int num[40][40];
int dfs(int from, int step) {
    if (step == 0){
        if (from == 0) return 1;
        else return 0;
    }    
    if (num[from][step] != -1)
        return num[from][step];
    num[from][step] = dfs((from + 1) % n, step - 1) + dfs((from + n - 1) % n, step - 1);
    return num[from][step];
}
int main() {
    //fre();
    while (scanf("%d%d", &n, &m) != EOF){
        memset(num, -1, sizeof(num));
        printf("%d\n", dfs(0, m));
    }
    return 0;
}

 

 

 

posted @ 2016-08-08 16:33  沐雨橙风fire  阅读(1531)  评论(0编辑  收藏  举报