奇怪的道路题解(状压dp)
题目链接:https://www.luogu.com.cn/problem/P6239
题意:
有\(n\)座城市,每座城市之间有\(m\)条道路相连。每座城市之前可以有多个道路,并且每个城市都被偶数条道路连接(0也算偶数)。此外,被连接的两个城市编号的差值不能大于\(k\)。现在问你有多少种连接方法满足以上条件,答案对\(10^9+7\)取模
思路:
看到k的范围和枚举,我们可以想到状压dp。定义\(dp[i][j][st]\), \(i\)为城市数量,\(j\)为道路数量,\(st\)为当前状态以及奇偶状态。那么就有 \(dp[i][j][st]+=dp[i][j-1][st\)^ 1 ^\((1<<(i-c)]\) (\(c\)为与\(i\)连边的点)
此外,我们需要转移下一个点的情况,也就有\(dp[i + 1][j][st << 1]=dp[i + 1][j][st << 1] + dp[i][j][st]\)
代码如下
#include <bits/stdc++.h>
using namespace std;
const int N = 32, NK = 10, mod = 1e9 + 7;
int dp[N][N][1 << NK];
int n, m, k;
int main()
{
cin >> n >> m >> k;
dp[2][0][0] = 1;
for(int i = 2; i <= n; i++)
{
for(int change = max(1, i - k); change <= i - 1; change++)
{
for(int j = 1; j <= m; j++)
{
for(int st = 0; st < 1 << (k + 1); st++)
dp[i][j][st] = (dp[i][j][st] + dp[i][j - 1][st ^ 1 ^ (1 << (i - change))]) % mod;
}
}
for(int j = 0; j <= m; j++)
{
for(int st = 0; st < 1 << k; st++)
dp[i + 1][j][st << 1] = (dp[i + 1][j][st << 1] + dp[i][j][st]) % mod;
}
}
cout << dp[n][m][0];
}
(如有错误多多指正)