题解:
我们可以对棋盘进行黑白染色,使得任意相邻的两个格子颜色不相同,然后进行二分图最大匹配。
Code:
1 class Solution { 2 public: 3 int N; 4 int M; 5 6 vector<vector<int>> dir{{1,0},{0,1},{-1,0},{0,-1}}; 7 8 int domino(int n, int m, vector<vector<int>>& broken) { 9 N=n; 10 M=m; 11 vector<vector<int>> grid(N*M,vector<int>(N*M,0)); 12 vector<int> bro(N*M,0); 13 for(auto b:broken){ 14 bro[b[0]*M+b[1]]=1; 15 } 16 for(int i=0;i<N*M;++i){ 17 if(bro[i]) continue; 18 int x=i/M; 19 int y=i%M; 20 if((x+y)%2!=0) continue; 21 for(int d=0;d<4;++d){ 22 int nx=x+dir[d][0]; 23 int ny=y+dir[d][1]; 24 if(nx<0 || nx>=N || ny<0 || ny>=M || bro[nx*M+ny]) continue; 25 grid[i][nx*M+ny]=1; 26 } 27 } 28 vector<int> mat(N*M,-1); 29 int res=0; 30 for(int i=0;i<N*M;++i){ 31 if(bro[i]) continue; 32 int x=i/M; 33 int y=i%M; 34 if((x+y)%2==0){ 35 vector<int> visited(N*M,0); 36 if(dfs(i,grid,visited, mat)){ 37 res++; 38 } 39 } 40 } 41 return res; 42 } 43 44 bool dfs(int u, vector<vector<int>> &grid, vector<int> &visited, vector<int> &mat){ 45 for(int i=0;i<M*N;++i){ 46 if(grid[u][i]){ 47 if(!visited[i]){ 48 visited[i]=1; 49 if(mat[i]==-1 || dfs(mat[i],grid,visited,mat)){ 50 mat[i]=u; 51 return true; 52 } 53 } 54 } 55 } 56 return false; 57 } 58 };
用最大流做:
1 class Solution { 2 public: 3 int N; 4 int M; 5 int S; 6 int T; 7 vector<vector<int>> dir{{1,0},{0,1},{-1,0},{0,-1}}; 8 9 int domino(int n, int m, vector<vector<int>>& broken) { 10 N=n; 11 M=m; 12 S=M*N; 13 T=M*N+1; 14 vector<vector<int>> grid(N*M+3,vector<int>(N*M+3,0)); //残余容量 15 vector<int> bro(N*M,0); 16 for(auto b:broken){ 17 bro[b[0]*M+b[1]]=1; 18 } 19 for(int i=0;i<N*M;++i){ 20 if(bro[i]) continue; 21 int x=i/M; 22 int y=i%M; 23 if((x+y)%2!=0){ 24 grid[i][T]=1; 25 continue; 26 } 27 grid[S][i]=1; 28 for(int d=0;d<4;++d){ 29 int nx=x+dir[d][0]; 30 int ny=y+dir[d][1]; 31 if(nx<0 || nx>=N || ny<0 || ny>=M || bro[nx*M+ny]) continue; 32 grid[i][nx*M+ny]=1; 33 } 34 } 35 int res=0; 36 37 while(true){ 38 vector<int> pre(N*M+3,-1); 39 bfs(grid,pre); 40 41 if(pre[T]==-1) break; 42 int minflow=INT_MAX; 43 int v=T; 44 while(true){ 45 int u=pre[v]; 46 minflow=min(minflow,grid[u][v]); 47 if(u==S) break; 48 v=u; 49 } 50 v=T; 51 while(true){ 52 int u=pre[v]; 53 grid[u][v]-=minflow; 54 grid[v][u]+=minflow; 55 if(u==S) break; 56 v=u; 57 } 58 res+=minflow; 59 } 60 61 return res; 62 } 63 64 void bfs(vector<vector<int>> &grid, vector<int> &pre){ 65 queue<int> q; 66 vector<int> visited(N*M+3,0); 67 visited[S]=1; 68 q.push(S); 69 while(!q.empty()){ 70 int cur=q.front(); 71 q.pop(); 72 if(cur==T) break; 73 for(int i=0;i<N*M+3;++i){ 74 if(grid[cur][i]>0 && visited[i]==0){ 75 visited[i]=1; 76 q.push(i); 77 pre[i]=cur; 78 } 79 } 80 } 81 } 82 };
状压DP:
class Solution { public: int M; int N; int domino(int n, int m, vector<vector<int>>& broken) { M=n; N=m; vector<int> b(n,0); for(auto bro:broken){ b[bro[0]]|=(1<<bro[1]); } vector<vector<int>> dp(n,vector<int>(1<<(N+N),-1)); return dfs(0,dp,b,0); } int dfs(int state, vector<vector<int>> &dp, vector<int> &b, int row){ if(dp[row][state]!=-1) return dp[row][state]; int res=0; for(int j=0;j<N-1;++j){ if(((1<<j)&b[row])==0 && ((1<<(j+1))&b[row])==0 && ((1<<j)&state)==0 && ((1<<(j+1))&state)==0){ int ns=state|(1<<j)|(1<<(j+1)); res=max(res,1+dfs(ns,dp,b,row)); } } if(row+1<M){ for(int j=0;j<N;++j){ if(((1<<j)&b[row])==0 && ((1<<j)&b[row+1])==0 && ((1<<j)&state)==0 && ((1<<(j+N))&state)==0 ){ int ns=state|(1<<j)|(1<<(j+N)); res=max(res,1+dfs(ns,dp,b,row)); } } int ns=state>>N; res=max(res,dfs(ns,dp,b,row+1)); } return dp[row][state]=res; } };