奇怪的道路题解(状压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];
}

(如有错误多多指正)

posted @ 2024-08-18 23:32  turt1e  阅读(22)  评论(0)    收藏  举报