版权声明:xgc原创文章,未经允许不得转载。 https://blog.csdn.net/xgc_woker/article/details/82431396
Description
在一个N*M个方格组成的棋盘内,有K个方格被称为特殊方格。我们要使用一组俄罗斯方块来覆盖这个棋盘,保证特殊方格不能被覆盖,非特殊方格只能被一个俄罗斯方块覆盖,求最多能容纳的俄罗斯方块的数量。
已知有以下三组俄罗斯方块,一个棋盘可能用其中的某一组。
Sample Input1
8 8 0 A
Sample Input2
7 6 6 C
3 1
3 6
5 3
5 4
5 7
6 7
Sample Output1
32
Sample Output2
12
这道题看一眼数据范围:有趣。
第一组,是个例题吧。。。
黑白染色,跑网络流。
第二组,只有一个k???
那不是
,n,m巨大,FFT一波。
第三组三进制状压DP(肯定可以跑过去,这辈子都不可能卡掉的)
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const double phi = acos(-1.0);
const int dx[4] = {0, 1, 0, -1};
const int dy[4] = {1, 0, -1, 0};
int _min(int x, int y) {return x < y ? x : y;}
int _max(int x, int y) {return x > y ? x : y;}
struct Complex {
double r, i;
Complex() {r = i = 0;}
Complex(double _r, double _i) {r = _r, i = _i;}
friend Complex operator + (Complex a, Complex b) {return Complex(a.r + b.r, a.i + b.i);}
friend Complex operator - (Complex a, Complex b) {return Complex(a.r - b.r, a.i - b.i);}
friend Complex operator * (Complex a, Complex b) {return Complex(a.r * b.r - a.i * b.i, a.i * b.r + a.r * b.i);}
} a[210000], b[210000];
struct node {
int len, a[210000];
node() {len = 0; memset(a, 0, sizeof(a));}
} A, B;
struct edge {
int x, y, c, next;
} e[210000]; int len, last[11000];
int st, ed, h[11000];
bool mp[110][110];
queue<int> q;
char ss[11], s1[210000], s2[210000];
int R[210000], c[210000];
int now, f[2][210000];
int n, m, C[15], D[15];
int plen[2], p[2][210000];
bool v[210000];
void back(int x) {
int num = 0;
while(x) C[++num] = x % 3, x /= 3;
}
int gett(int c[]) {
int hh = 1, sum = 0;
for(int i = 1; i <= m; i++) sum += hh * c[i], hh *= 3;
return sum;
}
void ins(int x, int y, int c) {
e[++len].x = x; e[len].y = y; e[len].c = c;
e[len].next = last[x]; last[x] = len;
e[++len].x = y; e[len].y = x; e[len].c = 0;
e[len].next = last[y]; last[y] = len;
}
bool bfs() {
memset(h, 0, sizeof(h)); h[st] = 1;
q.push(st);
while(!q.empty()) {
int x = q.front(); q.pop();
for(int k = last[x]; k; k = e[k].next) {
int y = e[k].y;
if(e[k].c && !h[y]) h[y] = h[x] + 1, q.push(y);
}
} if(!h[ed]) return 0; else return 1;
}
int dfs(int x, int flow) {
if(x == ed) return flow;
int tt = 0, minf;
for(int k = last[x]; k; k = e[k].next) {
int y = e[k].y;
if(h[y] == h[x] + 1 && e[k].c && tt < flow) {
minf = dfs(y, _min(e[k].c, flow - tt));
e[k].c -= minf; e[k ^ 1].c += minf;
tt += minf;
}
} if(!tt) h[x] = 0;
return tt;
}
int chu(int h) {
int las = 0;
for(int i = h; i >= 0; i--) {
c[i] += las;
las = (c[i] % 3) * 10;
c[i] /= 3;
} while(!c[h]) h--;
return h;
}
void fft(Complex *y, int len, int o) {
for(int i = 0; i < len; i++) if(i < R[i]) swap(y[i], y[R[i]]);
for(int i = 1; i < len; i *= 2) {
Complex wn(cos(phi / i), sin(o * phi / i));
for(int j = 0; j < len; j += i * 2) {
Complex w(1, 0);
for(int k = 0; k < i; k++, w = w * wn) {
Complex u = y[j + k];
Complex v = w * y[j + k + i];
y[j + k] = u + v;
y[j + k + i] = u - v;
}
}
} if(o == -1) for(int i = 0; i < len; i++) y[i].r /= len;
}
void Dfs(int k, int hh, int s) {
if(k > m) {
int p1 = gett(C), p2 = gett(D);
if(!v[p2]) v[p2] = 1, p[now][++plen[now]] = p2;
f[now][p2] = _max(f[now][p2], f[now ^ 1][p1] + s);
return ;
}
if(C[k] == 2) {D[k] = 1; Dfs(k + 1, hh, s); D[k] = 0; return ;}
if(hh <= n - 2 && !mp[hh][k] && !mp[hh + 1][k] && !mp[hh + 2][k] && !C[k] && !D[k]) D[k] = 2, Dfs(k + 1, hh, s + 1), D[k] = 0;
if(k <= m - 2 && !C[k] && !C[k + 1] && !C[k + 2] && !mp[hh][k] && !mp[hh][k + 1] && !mp[hh][k + 2]) Dfs(k + 3, hh, s + 1), D[k] = 0;
if(k <= m - 1 && hh < n) {
if(!C[k] && !C[k + 1] && !mp[hh][k] && !mp[hh][k + 1]) {
if(!D[k] && !mp[hh + 1][k]) D[k] = 1, Dfs(k + 2, hh, s + 1), D[k] = 0;
if(!mp[hh + 1][k + 1]) D[k + 1] = 1, Dfs(k + 2, hh, s + 1), D[k + 1] = 0;
}
if(!D[k] && C[k] != 2 && C[k + 1] != 2 && !mp[hh + 1][k] && !mp[hh + 1][k + 1]) {
if(!C[k] && !mp[hh][k]) D[k] = D[k + 1] = 1, Dfs(k + 2, hh, s + 1), D[k] = D[k + 1] = 0;
else if(!C[k + 1] && !mp[hh][k + 1]) D[k] = D[k + 1] = 1, Dfs(k + 2, hh, s + 1), D[k] = D[k + 1] = 0;
}
}
Dfs(k + 1, hh, s);
}
int main() {
scanf("%s%s", s1 + 1, s2 + 1);
int k; scanf("%d", &k);
scanf("%s", ss + 1);
if(ss[1] == 'A') {
n = 0, m = 0;
for(int i = 1; i <= strlen(s1 + 1); i++) n = n * 10 + s1[i] - '0';
for(int i = 1; i <= strlen(s2 + 1); i++) m = m * 10 + s2[i] - '0';
for(int i = 1; i <= k; i++) {
int x, y; scanf("%d%d", &x, &y);
mp[x][y] = 1;
}
len = 1; st = 0, ed = n * m + 1;
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++) if(((i + j) & 1) && !mp[i][j]){
for(int k = 0; k < 4; k++) {
int nx = i + dx[k], ny = j + dy[k];
if(nx > 0 && nx <= n && ny > 0 && ny <= m && !mp[nx][ny]) ins((i - 1) * m + j, (nx - 1) * m + ny, 1);
}
}
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++) if(((i + j) & 1) && !mp[i][j]){
ins(st, (i - 1) * m + j, 1);
}
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++) if(!((i + j) & 1) && !mp[i][j]){
ins((i - 1) * m + j, ed, 1);
}
int ans = 0;
while(bfs()) ans += dfs(st, 999999999);
printf("%d\n", ans);
} else if(ss[1] == 'B') {
n, m;
A.len = strlen(s1 + 1);
for(int i = 1; i <= A.len; i++) A.a[i] = s1[A.len - i + 1] - '0';
n = m = A.len - 1;
for(int i = 0; i <= n; i++) a[i].r = A.a[i + 1];
for(int i = 0; i <= m; i++) b[i].r = A.a[i + 1];
m += n + 2; int L = 0;
for(n = 1; n <= m; n *= 2) L++;
for(int i = 0; i < n; i++) R[i] = (R[i >> 1] >> 1) | (i & 1) << (L - 1);
fft(a, n, 1), fft(b, n, 1);
for(int i = 0; i <= n; i++) a[i] = a[i] * b[i];
fft(a, n, -1);
for(int i = 0; i < n; i++) c[i] = int(a[i].r + 0.5);
for(int i = 0; i < n; i++) {
c[i + 1] += c[i] / 10;
c[i] %= 10;
} while(n && c[n] <= 0) n--;
c[0]--; int u = 0;
while(c[u] < 0) c[u] += 10, c[u + 1]--;
n = chu(n);
for(int i = n; i >= 0; i--) printf("%d", c[i]);
printf("\n");
} else {
n = 0, m = 0;
for(int i = 1; i <= strlen(s1 + 1); i++) n = n * 10 + s1[i] - '0';
for(int i = 1; i <= strlen(s2 + 1); i++) m = m * 10 + s2[i] - '0';
for(int i = 1; i <= k; i++) {
int x, y; scanf("%d%d", &x, &y);
mp[x][y] = 1;
} now = 0; p[0][plen[0] = 1] = 0;
f[0][0] = 0;
for(int i = 1; i <= n; i++) {
memset(v, 0, sizeof(v));
now ^= 1; memset(f[now], -1, sizeof(f[now]));
plen[now] = 0;
for(int j = 1; j <= plen[now ^ 1]; j++) {
memset(C, 0, sizeof(C)); memset(D, 0, sizeof(D));
back(p[now ^ 1][j]);
Dfs(1, i, 0);
}
} int maxx = 0;
for(int i = 1; i <= plen[now]; i++)
maxx = _max(maxx, f[now][p[now][i]]);
printf("%d\n", maxx);
}
return 0;
}