1. 程式人生 > >zcmu 2121: 超級瑪麗

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; }