Date:2022.01.13
题意:盛况空前的足球赛即将举行。球赛门票售票处排起了球迷购票长龙。
按售票处规定,每位购票者限购一张门票,且每张票售价为50元。在排成长龙的球迷中有N个人手持面值50元的钱币,另有N个人手持面值100元的钱币。假设售票处在开始售票时没有零钱。试问这2N个球迷有多少种排队方式可使售票处不致出现找不出钱的尴尬局面。
思路:
f
[
i
]
[
j
]
f[i][j]
f[i][j]:前
i
i
i个人中有
j
j
j个人给的50情况下能找零的方案数。
状态转移:
①第
i
i
i个人给的是50:
f
[
i
]
[
j
]
+
=
f
[
i
−
1
]
[
j
−
1
]
【
i
>
=
1
∧
j
>
=
1
】
f[i][j]+=f[i-1][j-1]【i>=1 \wedge j>=1】
f[i][j]+=f[i−1][j−1]【i>=1∧j>=1】,即多了一张50。
②第
i
i
i个人给的是100:
f
[
i
]
[
j
]
+
=
f
[
i
−
1
]
[
j
+
1
]
【
i
>
=
1
∧
j
>
=
1
∧
j
+
1
<
=
i
−
1
】
f[i][j]+=f[i-1][j+1]【i>=1 \wedge j>=1 \wedge j+1<=i-1】
f[i][j]+=f[i−1][j+1]【i>=1∧j>=1∧j+1<=i−1】,即给了100找50,自己少了张50。
此外注意初始状态
f
[
0
]
[
0
]
=
1
f[0][0]=1
f[0][0]=1,因为一个人都没有也是一种方案。而且因为只有
2
×
n
2×n
2×n个人,因此终止状态一定是50都找完了,因此对应
2
×
n
2×n
2×n处没有零钱的状态,即
f
[
2
×
n
]
[
0
]
f[2×n][0]
f[2×n][0]。
代码如下:
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 55;
typedef long long LL;
LL a[N],f[N][N];
int main()
{
LL n,ans=0;cin>>n;
f[0][0]=1;
for(int i=1;i<=2*n;i++)
for(int j=0;j<=i;j++)
{
if(j-1>=0) f[i][j]+=f[i-1][j-1];
if(j+1<=i-1) f[i][j]+=f[i-1][j+1];
}
cout<<f[2*n][0];
return 0;
}