传送门:点击打开链接
题意:类似数独,不过还有另外一种限制,从左往右看,从右往左看,从上往下看,从下往上看,看到的塔数应该是固定的。
思路:暴搜。好久没暴搜了,呼呼。。
#include<map> #include<set> #include<cmath> #include<ctime> #include<stack> #include<queue> #include<cstdio> #include<cctype> #include<string> #include<vector> #include<cstring> #include<iomanip> #include<iostream> #include<algorithm> #include<functional> #define fuck(x) cout<<"["<<x<<"]" #define FIN freopen("input.txt","r",stdin) #define FOUT freopen("output.txt","w+",stdout) using namespace std; typedef long long LL; typedef pair<int, int>PII; const int MX = 1e2 + 5; const int mod = 1e9 + 7; const int INF = 0x3f3f3f3f; char s[MX][MX]; int vis[2][MX][MX], r, n; struct Point { int x, y; } P[MX]; bool left(int i, int tot) { int ret = 0, now = 0, cnt = 0; for(int j = 1; j <= n; j++) { if(s[i][j] > now) now = s[i][j], ret++; if(s[i][j]) cnt++; } if(cnt == n) return ret == tot; return ret <= tot; } bool right(int i, int tot) { int ret = 0, now = 0, cnt = 0; for(int j = n; j >= 1; j--) { if(s[i][j] > now) now = s[i][j], ret++; if(s[i][j]) cnt++; } if(cnt == n) return ret == tot; return true; } bool top(int j, int tot) { int ret = 0, now = 0, cnt = 0; for(int i = 1; i <= n; i++) { if(s[i][j] > now) now = s[i][j], ret++; if(s[i][j]) cnt++; } if(cnt == n) return ret == tot; return ret <= tot; } bool foot(int j, int tot) { int ret = 0, now = 0, cnt = 0; for(int i = n; i >= 1; i--) { if(s[i][j] > now) now = s[i][j], ret++; if(s[i][j]) cnt++; } if(cnt == n) return ret == tot; return true; } bool check(int i, int j, int t) { if(vis[0][i][t]) return false; if(vis[1][j][t]) return false; s[i][j] = t; if(s[i][0] && !left(i, s[i][0])) return s[i][j] = 0; if(s[i][n + 1] && !right(i, s[i][n + 1])) return s[i][j] = 0; if(s[0][j] && !top(j, s[0][j])) return s[i][j] = 0; if(s[n + 1][j] && !foot(j, s[n + 1][j])) return s[i][j] = 0; vis[0][i][t] = vis[1][j][t] = 1; return true; } bool check_all() { for(int i = 0; i <= n + 1; i++) { for(int j = 0; j <= n + 1; j++) { s[i][j] = isdigit(s[i][j]) ? s[i][j] - '0' : 0; if(1 <= i && i <= n && 1 <= j && j <= n) { int t = s[i][j]; if(t) { if(vis[0][i][t]) return false; if(vis[1][j][t]) return false; vis[0][i][t] = vis[1][j][t] = 1; } else P[r].x = i, P[r].y = j, r++; } } } for(int i = 1; i <= n; i++) { if(s[i][0] && !left(i, s[i][0])) return false; if(s[i][n + 1] && !right(i, s[i][n + 1])) return false; if(s[0][i] && !top(i, s[0][i])) return false; if(s[n + 1][i] && !foot(i, s[n + 1][i])) return false; } return true; } bool DFS(int c) { if(c == r) return true; for(int x = 1; x <= n; x++) { if(!check(P[c].x, P[c].y, x)) continue; if(DFS(c + 1)) return true; vis[0][P[c].x][x] = vis[1][P[c].y][x] = s[P[c].x][P[c].y] = 0; } return false; } int main() { int T; //FIN; scanf("%d", &T); while(T--) { r = 0; memset(vis, 0, sizeof(vis)); scanf("%d", &n); for(int i = 0; i <= n + 1; i++) { scanf("%s", s[i]); } if(!check_all() || !DFS(0)) printf("no\n\n"); else { for(int i = 1; i <= n; i++) { for(int j = 1; j <= n; j++) printf("%d", (int)s[i][j]); printf("\n"); } printf("\n"); } } return 0; }