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 }