F - Military Class
There is a military class of 2∗n soldiers, and the commander wants all of them to get partnered into n pairs. He divides the soldiers into two lines of length n, and numbers the soldiers in both lines from 1 to n.
The ith numbered soldiers in the first line can be partnered with the jth numbered soldiers in the second line if |i−j|≤e. However, there are k pairs of soldiers that cannot be paired together. You need to print the number of ways you can match the soldiers into n pairs such that the constraints above are met. One way is different than the other if at least one soldiers has a different partner.
Input
The first line contains 3 integers n,e,k(1≤n≤2000,0≤e≤4,0≤k≤2000), the number of soldiers in each line, the value that determines the range, and the number of invalid pairs, respectively.
Each of the next k lines contains two integers ui,vi(1≤ui,vi≤n), the number of the soldiers from the first line and the number of the soldiers from the second line that cannot be matched together respectively. No pair of soldiers will appear twice in the input.
Output
Output the number of ways modulo
1
0
9
+
7
10^9+7
109+7, on a single line.
题解:
我们的e范围很小最大就是2*e+1=9,所以可以考虑状压。dp[i][j]代表选择第i个人并且状态是j的方案数。这里用一维数组就可以了。所以第一层循环就是匹配到第几个了,第二层循环就是和9个人里面的谁匹配,然后枚举之前的匹配状态如果匹配过则跳过。最后把匹配到第n个人的所有状态方案数加起来就可以了。
解释一下为啥要右边移动,因为我们选最右边的时候在二进制的表示下滑到了最左边。所以我们在选人的时候二进制是反的。那么我们当前位置的状态用上一个位置的状态表示就是右边移动(因为平常我们在本子上写的时候上一个窗口是左移。)然后就可以用上一个状态来更新当前状态了。
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e3+7;
const int mod=1e9+7;
int dp[1<<10|10],tmp[1<<10|10];
bool g[N][N];
signed main()
{
int state=(1<<9)-1;
int n,e,m; cin>>n>>e>>m;
for(int i=1;i<=m;i++) {
int a,b; cin>>a>>b;
g[a][b]=1;
}
dp[0]=1;
for(int i=1;i<=n;i++){
memset(tmp,0,sizeof tmp);
for(int k=-e;k<=e;k++){
int j=k+i;
if(j<1||j>n) continue;
if(g[i][j]) continue;
for(int s=0;s<=state;s++){
if((s>>1)&(1<<(k+4))) continue;
tmp[(s>>1)|(1<<(k+4))]=(tmp[(s>>1)|(1<<(k+4))]+dp[s])%mod;
}
}
memcpy(dp,tmp,sizeof tmp);
}
int res=0;
for(int s=0;s<=state;s++){
res=(res+dp[s])%mod;
}
cout<<res<<endl;
}