考場上連暴力都不會打的碼農題,深搜是真的難 /kkios
cout<<"\\";
2.怎麼處理不在一個環裏,能夠考慮並查集,\(f\)數組的下標爲該元素位於矩陣中的個數
例如: 在$3 \times 3 $的矩陣中 \((2,2)\) 座標指的是交點的座標
能夠表示爲 5算法
(1,1)---->1 (1,2)---->2 (1,3)---->3 (1,4)---->4 (2,1)---->5 (2,2)---->6 (2,3)---->7 (2,4)---->8 (3,1)---->9 (3,2)---->10 (3,3)---->11 (3,4)---->12
若是兩個點位於同一個並查裏那就不能連邊,若是不在,那麼就能夠連邊
此並查集不一樣於通常的並查集
其初值不能爲0 ,並且其不能進行路徑壓縮,本身想一下就會明白,若是路徑壓縮會這樣數組
3 .樣例輸入實際上是有問題的
樣例輸入:app
2 3 1.1. ...0 .3.. ..2. 5 .21... ..33.0 ...... ..33.. 0..33. ....11
輸出:函數
\// \\\ /\/ /\\// //\\\ \\\// \/\\/ ///\\
再說一遍這是spj不要看樣例不對就覺得本身寫錯了,可能算法不同也就不同spa
上面的前置知識中已經解決了一個最大的問題,環的問題,剩下的就是怎麼搜索
從\((1,1)\)開始搜索,逐行進行處理,由於每個格子要不放""要不就是放"/"由於是spj咱們能夠考慮首先放"",而後判斷放"/",種徹底不反悔的深搜,一搜到底,適用的範圍貌似不是很大code
能夠考慮從\((1,1)\)開始搜索, 首先考慮放「/」 若是不合法,那就回溯,從新放置"",這種想法想的很容易可是想要實現十分困難,反正這位大佬碼量驚人,竟然還真寫出來了%%%%blog
#include <iostream> #include <cstdio> #include <cmath> #include <cstring> #include <string> #define ll long long using namespace std; const int N = 150; const int dx[4] = {0, 0, 1, 1}; const int dy[4] = {0, 1, 0, 1}; int n ; int mapp[50][50] ; int cnt[N][N]; // 這個點已經鏈接了幾條邊 int lim[N][N]; //一個格子能夠拓展的方向 char ans[N][N]; // 一開始我是char想直接輸出,我也不知爲啥不行 int f[N*N]; bool flag; void print() { puts(""); for(int i = 1 ; i <= n;i++) { for(int j = 1 ; j <= n ;j++) { cout<<mapp[i][j] <<" "; } puts(""); } } //檢驗本身輸入的函數 bool check(int x,int y){ if(mapp[x][y] == -1) return true; if(cnt[x][y] <= mapp[x][y] && cnt[x][y] + lim[x][y] >= mapp[x][y]) return true; return false ; } //判斷合法 int findf(int x) { if( !f[x] ) return x; return f[x] = findf(f[x]); } void dfs(int x, int y) { if (y == n) { y = 1 , x++; } if(x == n ) { flag = 1; return ; } // 這裏由於是逐行搜索,n++後,不會檢查第 n+1 行的交點,第n+1行下面已經沒有格子了 int f1 , f2 ,pd = 0; ++cnt[x][y], ++cnt[x + 1][y + 1]; --lim[x][y],--lim[x+1][y+1],--lim[x+1][y],--lim[x][y+1]; //由於一個格子只能放一種 \ 或者 / 因此 一個格子的四個角都要減小拓展的方向 //第一種狀況 \ for(int i = 0 ; i < 4 ;i++) { int tx = x + dx[i] , ty = y + dy[i]; if(!check(tx,ty)) { pd = 1; break; } } if(!pd) { f1 = findf((x - 1) * n + y),f2 = findf(x * n + y + 1 ) ; if(f1 != f2) { ans[x][y] = 1; // 1 ---------> \ f[f1] = f2; dfs(x,y+1); if(flag) return ; f[f1] = 0; } } --cnt[x][y], --cnt[x+1][y+1]; ++cnt[x+1][y] ,++cnt[x][y+1]; // 更換爲另外一種狀況 / pd = 0; for(int i = 0 ; i < 4 ;i++) { int tx = x + dx[i] , ty = y + dy[i]; if(!check(tx,ty)) { pd = 1; break; } } if(!pd) { f1 = findf(x * n + y ),f2 = findf((x - 1) * n + y + 1) ; if(f1 != f2) { ans[x][y] = 0; // 0 ------------> / f[f1] = f2; dfs(x,y+1); if(flag) return ; f[f1] = 0; } } --cnt[x+1][y] ,--cnt[x][y+1]; ++lim[x][y] ,++lim[x+1][y+1] ,++lim[x+1][y], ++lim[x][y + 1] ; //深搜回溯 } int main() { // freopen("gokigen.in","r",stdin); // freopen("gokigen.out","w",stdout); int T; cin>> T; while(T--) { // memset(cnt , 0 , sizeof(cnt)); memset(f,0,sizeof(f)); flag = 0; //多組不清我是sb cin>> n; n++; for(int i = 1 ; i <= n ;i++) { for(int j = 1 ; j <= n ;j++) { lim[i][j] = 4; char ch = getchar() ; if(ch == '\n' && i + j != 2 * n ) ch = getchar(); if(ch == '.') mapp[i][j] = -1; else mapp[i][j] = (ch - '0'); if((i == 1 || i == n) && (j == 1 || j == n)) { lim[i][j] = 1; continue; } if(i == 1 || i == n || j == 1 || j == n) lim[i][j] = 2; } } dfs(1,1); for(int i = 1 ; i < n ;i++) { for(int j = 1 ; j < n ;j++) { if(!ans[i][j]) cout<<"/"; else cout <<"\\"; } puts(""); } } return 0; }