USACO4.4 重疊的影象 Frame Up
阿新 • • 發佈:2020-11-29
Solution
今天上午測試題...最後幾分鐘才看到要輸出所有解,於是爆成了 44pts...
根據輸入可以得到所有字母構成的矩形。如果字元 \(i\) 出現在了字元 \(j\) 的矩形上,那麼 \(i\) 的影象一定在 \(j\) 的影象上方,從 \(j\) 向 \(i\) 連邊。
跑一個拓撲排序,每次可以選的是佇列裡所有點之一。因此需要 dfs 所有可能情況,最後存到變數裡按照字典序輸出。
手寫佇列要注意,不能直接對佇列排序,dfs 時會造成混亂。
Code
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int N = 2333; char a[N][N]; int n, m, Num = 0, tot = 0, res = 0; int vis[N], lx[N], rx[N], ly[N], ry[N], e[N][N]; int q[N], du[N], use[N]; string ans[2333333]; void dfs(int num, int stp) { if(stp == Num) { res++; ans[res] = ""; for(int i = 1; i <= stp; i++) ans[res] += (char)(use[i]); return ; } for(int i = 1; i <= num; i++) { int x = q[i], cnt = num - 1; for(int j = i; j < num; j++) q[j] = q[j + 1]; for(int j = 'A'; j <= 'Z'; j++) { if(vis[j] && e[x][j]) { du[j]--; if(du[j] == 0) q[++cnt] = j; } } use[stp + 1] = x; dfs(cnt, stp + 1); for(int j = num; j > i; j--) q[j] = q[j - 1]; q[i] = x; for(int j = 'A'; j <= 'Z'; j++) if(vis[j] && e[x][j]) du[j]++; } } int main() { scanf("%d%d", &n, &m); memset(e, 0, sizeof(e)); memset(lx, 0x3f, sizeof(lx)); memset(ly, 0x3f, sizeof(ly)); memset(vis, 0, sizeof(vis)); for(int i = 1; i <= n; i++) for(int j = 1; j <= m; j++) { cin >> a[i][j]; if(a[i][j] >= 'A' && a[i][j] <= 'Z') { if(!vis[a[i][j]]) { vis[a[i][j]] = 1; Num++; } lx[a[i][j]] = min(lx[a[i][j]], i); ly[a[i][j]] = min(ly[a[i][j]], j); rx[a[i][j]] = max(rx[a[i][j]], i); ry[a[i][j]] = max(ry[a[i][j]], j); } } for(int i = 'A'; i <= 'Z'; i++) { if(!vis[i]) continue; for(int j = ly[i]; j <= ry[i]; j++) { char ch1 = a[lx[i]][j], ch2 = a[rx[i]][j]; if(vis[ch1] && ch1 != i) e[i][ch1] = 1; if(vis[ch2] && ch2 != i) e[i][ch2] = 1; } for(int j = lx[i]; j <= rx[i]; j++) { char ch1 = a[j][ly[i]], ch2 = a[j][ry[i]]; if(vis[ch1] && ch1 != i) e[i][ch1] = 1; if(vis[ch2] && ch2 != i) e[i][ch2] = 1; } } memset(du, 0, sizeof(du)); for(int i = 'A'; i <= 'Z'; i++) { if(!vis[i]) continue; for(int j = 'A'; j <= 'Z'; j++) { if(!vis[j]) continue; if(e[i][j] == 1) du[j]++; } } for(int i = 'A'; i <= 'Z'; i++) { if(!vis[i]) continue; if(du[i] == 0) { tot++; q[tot] = i; } } dfs(tot, 0); sort(ans + 1, ans + res + 1); for(int i = 1; i <= res; i++) cout << ans[i] << endl; return 0; }