一旦选择,便无法回头
题目链接
简要题面:
有一个无向图(可能不连通),
于是某个大聪明打出了这样的代码:
signed 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 now_state = 0; now_state < (1 << (k + 1)); now_state++) {
dp[i][j][now_state] = (dp[i][j][now_state] + dp[i][j - 1][now_state ^ 1 ^ (1 << i - change)]) % mod;
}
}
}
}
cout<<dp[n][m][0]<<'\n';
return 0;
}
诶,怎么不对呢?怎么都输出 0 啊。形如这样的情况,说明漏了转移。
我们观察到,每一次多一个点的情况都要转移过去,这也是没有讨论全面的一个错误。
添加一个发送式转移至下个阶段:
坑点:位运算要打括号!取模要小心!
Code:
#include<bits/stdc++.h>
using namespace std;
const int mod = 1e9 + 7;
const int Data_Range_Of_N = 30 + 5;
const int Data_Range_Of_K = 10 + 5;
int n, m, k;
int dp[Data_Range_Of_N][Data_Range_Of_N][1 << Data_Range_Of_K];
signed main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
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 now_state = 0; now_state < (1 << (k + 1)); now_state++) {
dp[i][j][now_state] = (dp[i][j][now_state] + dp[i][j - 1][now_state ^ 1 ^ (1 << i - change)]) % mod;
}
}
}
for(int j = 0;j<=m;j++) {
for(int now_state = 0;now_state < (1 << k);now_state++) {
dp[i+1][j][now_state << 1] = (dp[i][j][now_state] + dp[i+1][j][now_state << 1]) % mod;
}
}
}
cout<<dp[n][m][0]<<'\n';
return 0;
}