(所有的图均来自于”将狼踩尽”…)
题目大意:
题意:在如下的图中分别有
n∗n
和
m∗m
的矩形,放车使得不相互攻击(横竖攻击)。求放
K
个车的方案数。
分析:
我们可以把不一般的情况通过平移变成一般情况,还不懂就研究代码去吧。
AC code:
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <algorithm>
#include <string>
#include <sstream>
#include <iostream>
#include <map>
#include <set>
#include <list>
#include <stack>
#include <queue>
#include <vector>
#define ONLINE_JUDGE
typedef long long LL;
typedef double DB;
typedef long double LD;
using namespace std;
const int MAXN = 29;
const LL MOD = 1e9;
int n, m, w, h, should;
int h1, h2, h3;
int w1, w2, w3;
struct BI
{
LL a[10];
BI()
{
memset(a, 0, sizeof(a));
a[0] = 1;
}
void init(int x) {a[1] = x;}
void clear()
{
memset(a, 0, sizeof(a));
a[0] = 1;
}
void shift()
{
for(int i = 1; i <= a[0]; ++i)
{
a[i+1] += a[i]/MOD;
a[i] %= MOD;
}
while(a[a[0]+1])
{
a[0]++;
a[a[0]+1] += a[a[0]]/MOD;
a[a[0]] %= MOD;
}
}
void operator += (const BI &b)
{
int maxsize = max(a[0], b.a[0]);
for(int i = 1; i <= maxsize; ++i)
a[i] += b.a[i];
shift();
}
friend BI operator * (const BI &a, int k)
{
BI b = a;
for(int i = 1; i <= b.a[0]; ++i)
b.a[i] *= k;
b.shift();
return b;
}
void print()
{
printf("%d", (int)a[a[0]]);
for(int i = a[0]-1; i >= 1; --i)
printf("%09d", (int)a[i]);
}
bool is_zero()
{
return a[0] == 1 && !a[1];
}
}f[2][MAXN][MAXN][MAXN], ans;
int main()
{
#ifndef ONLINE_JUDGE
freopen("sgu241.in", "r", stdin);
freopen("sgu241.out", "w", stdout);
#endif
scanf("%d%d%d%d%d", &n, &m, &w, &h, &should);
w = min(w, n);
h = min(h, n);
if(m+w <= n && m+h <= n)
{
h1 = h2 = h3 = n;
w1 = w2 = w3 = n;
}
else
{
if(m+w > n && m+h < n) h = n-m;
if(m+w < n && m+h > n) w = n-m;
h1 = h, h2 = n, h3 = h1+m;
w1 = w, w2 = n, w3 = w1+m;
}
f[0][0][0][0].init(1);
for(int i = 1; i <= w1; ++i)
{
int now = i&1, last = now^1;
for(int j = 0; j <= h1; ++j)
for(int k = 0; k <= h2-h1; ++k)
if(!f[last][j][k][0].is_zero())
{
f[now][j+1][k][0] += f[last][j][k][0]*(h1-j);
f[now][j][k+1][0] += f[last][j][k][0]*(h2-h1-k);
f[now][j][k][0] += f[last][j][k][0];
f[last][j][k][0].clear();
}
}
for(int i = w1+1; i <= w2; ++i)
{
int now = i&1, last = now^1;
for(int j = 0; j <= h1; ++j)
for(int k = 0; k <= h2-h1; ++k)
for(int p = 0; p <= h3-h2; ++p)
if(!f[last][j][k][p].is_zero())
{
f[now][j+1][k][p] += f[last][j][k][p]*(h1-j);
f[now][j][k+1][p] += f[last][j][k][p]*(h2-h1-k);
f[now][j][k][p+1] += f[last][j][k][p]*(h3-h2-p);
f[now][j][k][p] += f[last][j][k][p];
f[last][j][k][p].clear();
}
}
for(int i = w2+1; i <= w3; ++i)
{
int now = i&1, last = now^1;
for(int j = 0; j <= h1; ++j)
for(int k = 0; k <= h2-h1; ++k)
for(int p = 0; p <= h3-h2; ++p)
if(!f[last][j][k][p].is_zero())
{
f[now][j][k+1][p] += f[last][j][k][p]*(h2-h1-k);
f[now][j][k][p+1] += f[last][j][k][p]*(h3-h2-p);
f[now][j][k][p] += f[last][j][k][p];
f[last][j][k][p].clear();
}
}
for(int i = 0; i <= h1; ++i)
for(int j = 0; j <= h2-h1; ++j)
for(int k = 0; k <= h3-h2; ++k)
if(i+j+k == should)
ans += f[w3&1][i][j][k];
ans.print();
#ifndef ONLINE_JUDGE
fclose(stdin);
fclose(stdout);
#endif
return 0;
}