好像没看到这题题解?
爆搜可以过45%
这题可以用状压dp,和炮兵布阵那题很像
d
[
i
]
[
j
]
[
k
]
[
s
]
d[i][j][k][s]
d[i][j][k][s]表示处理到i行,第i行状态为j,第i-1行状态为k,前i行一共放了s个马时的方案数
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 7;
const int maxm = 101;
const int mod=1e9+7;
int cnt = 0, nums[1<<maxn], sit[1 << maxn], dp[maxm][1 << maxn][1 << maxn][21], ans = 0, n, m, q;
vector<int> mt[1<<maxn];
void dfs(int bit, int num, int step)
{
if (step >= n)
{
sit[++cnt] = bit;
nums[cnt] = num;
return;
}
dfs(bit, num, step + 1);
dfs(bit + (1 << step), num + 1, step + 1);
}
void pre()
{
for (int i = 1; i <= cnt; i++)
for (int j = 1; j <= cnt; j++)
{
if ((sit[i] << 2) & sit[j])
continue;
if ((sit[i] >> 2) & sit[j])
continue;
mt[i].push_back(j);
}
for (int i = 1; i <= cnt; i++)
for (int j = 0; j < mt[i].size(); j++)
{
dp[2][i][mt[i][j]][nums[i] + nums[mt[i][j]]] = 1;
}
}
int main()
{
cin >> n >> m >> q;
if (n > m)
swap(n, m);
dfs(0, 0, 0);
pre();
ans = 0;
if (m == 1)
{
for (int i = 1; i <= cnt; i++)
{
if (nums[i] == q)
ans++;
}
cout << ans << endl;
}
else
{
for (int i = 3; i <= m; i++)
for (int j = 1; j <= cnt; j++)
for (int k = 0; k < mt[j].size(); k++)
{
int p = mt[j][k];
for (int s = 0; s < mt[p].size(); s++)
{
int h = mt[p][s];
if ((sit[h] << 1) & sit[j])
continue;
if ((sit[h] >> 1) & sit[j])
continue;
for (int w = q; w >= nums[j]; w--)
{
dp[i][j][p][w] = (dp[i][j][p][w]+dp[i-1][p][h][w - nums[j]])%mod;
}
}
}
for (int i = 1; i <= cnt; i++)
for (int j = 0; j < mt[i].size(); j++){
ans += dp[m][i][mt[i][j]][q];
ans%=mod;
}
cout << ans << endl;
}
return 0;
}
n=6 m=100 k=20跑了157ms