LCP 4. 覆盖

题目链接

 

题解:

我们可以对棋盘进行黑白染色,使得任意相邻的两个格子颜色不相同,然后进行二分图最大匹配。

 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;
    }
};

 

posted @ 2020-02-02 09:41  feibilun  阅读(207)  评论(0编辑  收藏  举报