zcmu 2121: 超級瑪麗
阿新 • • 發佈:2018-11-14
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;
}