Tsinsen-A1488 : 魔法波【高斯消元+异或方程组】

  高斯消元。

  自己只能想出来把每一个点看成一个变量,用Xi表示其状态,这样必定TLE,n^2 个变量,再加上3次方的高斯消元(当然,可以用bitset压位)。

  正解如下:

    我们把地图划分成一个个的横条和竖条,对于点i,我们用Li,Ri分别表示横着和竖着穿过它的,显然,对于每一个点,有且仅有一个L块和R块穿过。

    得到第一个方程    YLi = sigma(Xp) p属于Li,YRi = sigma(Xp) p属于Ri --> sigma(Xp) xor Yi = 0.

    接着我们考虑, Si xor YLi xor YRi xor Xi = 1 这是第二个方程,对其移项,那么变成了 Xi = 1 xor Si xor YLi xor YRi.

    将其回带到第一个式子中即可,对于每一个点,放在不同的两个方程里,一个横的,一个竖的即可。

  TLE50 我将枚举自由变量的语句删除后,发现没有TLE了,但是最多只有2000个障碍物,最多是O(2000^2)的复杂度,可能是数据加强了吧。

 1 #include <bits/stdc++.h>
 2 #define rep(i, a, b) for (int i = a; i <= b; i++)
 3 #define REP(i, a, b) for (int i = a; i < b; i++)
 4 #define drep(i, a, b) for (int i = a; i >= b; i--)
 5 #define pb push_back
 6 #define mp make_pair
 7 #define clr(x) memset(x, 0, sizeof(x));
 8 #define xx first
 9 #define yy second
10 using namespace std;
11 typedef long long i64;
12 typedef pair<int, int> pii;
13 const int inf = ~0U>>1;
14 const i64 INF = ~0ULL>>1;
15 //***************************
16 const int maxn = 805;
17 char ma[maxn][maxn];
18 pii no[maxn][maxn];
19 int n, cnt_x, cnt_eq;
20 bitset<2005> eq[2005];
21 void init() {
22     rep(i, 1, n) {
23         if (ma[i][1] != 'X') no[i][1].xx = ++cnt_x;
24         rep(j, 2, n) {
25             if (ma[i][j] == 'X') continue;
26             if (no[i][j - 1].xx) no[i][j].xx = no[i][j - 1].xx;
27             else no[i][j].xx = ++cnt_x;
28         }
29     }
30     rep(i, 1, n) {
31         if (ma[1][i] != 'X') no[1][i].yy = ++cnt_x;
32         rep(j, 2, n) {
33             if (ma[j][i] == 'X') continue;
34             if (no[j - 1][i].yy) no[j][i].yy = no[j - 1][i].yy;
35             else no[j][i].yy = ++cnt_x;
36         }
37     }
38     cnt_eq = cnt_x;
39     rep(i, 1, cnt_x) eq[i].set(i);
40     rep(i, 1, n) rep(j, 1, n) if (no[i][j].xx) {
41         int l = no[i][j].xx, r = no[i][j].yy;
42         eq[l].flip(l), eq[l].flip(r), eq[r].flip(l), eq[r].flip(r);
43         if (1 ^ (ma[i][j] - '0')) eq[l].flip(cnt_x + 1), eq[r].flip(cnt_x + 1);
44     }
45 }
46 void gauss() {
47     rep(i, 1, cnt_x) {
48         rep(j, i, cnt_eq) if (eq[j][i] > eq[i][i]) { swap(eq[j], eq[i]); break; }
49         rep(j, 1, cnt_eq) if (i != j && eq[j][i]) eq[j] ^= eq[i];
50     }
51 }
52 int choice[2005];
53 int main() {
54     scanf("%d", &n);
55     rep(i, 1, n) scanf("%s", ma[i] + 1);
56     init();
57     gauss();
58     drep(i, cnt_x, 1) {
59         if (eq[i][i]) {
60             choice[i] = eq[i][cnt_x + 1];
61             drep(j, cnt_x, i + 1) if (eq[i][j]) choice[i] ^= choice[j];
62         }
63         else choice[i] = 0;
64     }
65     rep(i, 1, n) {
66         rep(j, 1, n) 
67             if (ma[i][j] == 'X') printf("0");
68             else printf("%d", 1 xor (ma[i][j] - '0') xor choice[no[i][j].xx] xor choice[no[i][j].yy]);
69         puts("");
70     }
71     return 0;
72 }
View Code
原文地址:https://www.cnblogs.com/y7070/p/5025816.html