zcmu 2121: 超级玛丽

2121: 超级玛丽

Time Limit: 1 Sec Memory Limit: 128 MB

Description

大家都知道"超级玛丽"是一个很善于跳跃的探险家,他的拿手好戏是跳跃,但它一次只能向前跳一步或两步。有一次,他要经过一条长为n的羊肠小道,小道中有m个陷阱,这些陷阱都位于整数位置,分别是a1,a2,…am,陷入其中则必死无疑。显然,如果有两个挨着的陷阱,则玛丽是无论如何也跳过不去的。
现在给出小道的长度n,陷阱的个数及位置。求出玛丽从位置1开始,有多少种跳跃方法能到达胜利的彼岸(到达位置n)。

Input

第一行为两个整数n,m
第二行为m个整数,表示陷阱的位置

Output

一个整数。表示玛丽跳到n的方案数

Sample Input

4 1
2
Sample Output

1
HINT

40>=n>=3,m>=1

n>m;

陷阱不会位于1及n上

Source

算法提高

【分析】
遇到这种问题最开始就是想到画图,看看是怎么跳的;根据题目的要求,超级玛丽跳过陷阱时,只能是从陷阱的前一个位置跳到陷阱的后一个位置,所以跳过陷阱的过程是没有多种情况的,那么多种情况就是分布在两个陷阱之间的的路程,也就是说,只需要把每一段没有陷阱的路程中的跳跃方式的种类算出来,然后相乘就好了;
每一段的跳跃方式的种类,就要用到排列组合了。

【代码】

#include <iostream>
#include <algorithm>
#include <bits/stdc++.h>
using namespace std;
 
int a[50];//a数组用来存放陷阱的位置
int n,m;
 
int main()
{
        scanf("%d%d",&n,&m);
        a[0]=0;  //玛丽从位置1开始跳,可以假设位置0有一个陷阱,便于下面的计算
        for(int i=1; i<=m; i++)
        {
            scanf("%d",&a[i]);
        }
        a[m+1]=n+1;//玛丽跳到位置n结束,可以假设位置n+1有一个陷阱
        sort(a,a+m+2);//排序,很重要,之前没排序就wa了
        int ans=1;
        for(int i=1; i<=m+1; i++)
        {
            int sum1=0;
            for(int j=a[i]-a[i-1]-2,k=0; j>=k; j--,k++)//开始排列组合
            {
                int lb=1,num=1;
                for(int x=k; x>0; x--)//计算排列的分母
                    lb=x*lb;
                for(int y1=j,y2=k; y2>0; y2--,y1--)//计算排列的分子
                    num=num*y1;
                sum1+=num/lb;
            }
            ans*=sum1;
        }
        printf("%d\n",ans);
    return 0;
}

你可能感兴趣的:(zcmu)