• ZOJ 3781 Paint the Grid Reloaded(DFS连通块缩点+BFS求最短路)


    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5268

    题目大意:字符一样并且相邻的即为连通。每次可翻转一个连通块X(O)的颜色,问至少改变几次使得图上所有字符都相等。

    解题思路:

    1) dfs( 建图 ) ,因为翻转的时候每翻转连通块中一个整个连通块都翻转,
    这样你可以将其看成一个有边相连的无向图,每个边的两个顶点颜色都不一样。

    2) bfs( 寻找最优解 ) , 建完图后就需要翻转计算最优解,可以枚举从每一点开始翻转所得到的最小步数,那怎样寻找最小步数 ?
    假如从 v 这个顶点出发,那么与 v 相邻的顶点颜色必定都与 v 相反,so~> 你只需要把 v的颜色翻转,
    v与它相邻的所有顶点都是同一个颜色,这时可以把这些顶点看成一个连通块(顶点),再向四周扩展,
    再次扩展时,周围的颜色必定与此连通块颜色相反,再将它变成与周围顶点相同的颜色,
    这样又合并成为一个连通块……这样一直进行下去取最大步数。最后从最大步数中取出最小的步数即为最优解。

    代码:

      1 #include<cstdio>
      2 #include<cmath>
      3 #include<cctype>
      4 #include<cstring>
      5 #include<iostream>
      6 #include<algorithm>
      7 #include<vector>
      8 #include<queue>
      9 #include<set>
     10 #include<map>
     11 #include<stack>
     12 #include<string>
     13 #define lc(a) (a<<1)
     14 #define rc(a) (a<<1|1)
     15 #define MID(a,b) ((a+b)>>1)
     16 #define fin(name)  freopen(name,"r",stdin)
     17 #define fout(name) freopen(name,"w",stdout)
     18 #define clr(arr,val) memset(arr,val,sizeof(arr))
     19 #define _for(i,start,end) for(int i=start;i<=end;i++)  
     20 #define FAST_IO ios::sync_with_stdio(false);cin.tie(0);
     21 using namespace std;
     22 typedef long long LL;
     23 const int N=50+5;
     24 const int INF=0x3f3f3f3f;
     25 const double eps=1e-10;
     26 
     27 int n,m,cnt;
     28 int path[N*N],vis[N][N];
     29 int d[4][2]={0,1,1,0,0,-1,-1,0};
     30 char mp[N][N];
     31 vector<int>v[N*N];
     32 
     33 bool judge(int x,int y){
     34     if(x>=1&&y>=1&&x<=n&&y<=m&&!vis[x][y])
     35         return true;
     36     return false;
     37 }
     38 
     39 void dfs(int x,int y){
     40     vis[x][y]=cnt;
     41     for(int i=0;i<4;i++){
     42         int xx=x+d[i][0];
     43         int yy=y+d[i][1];
     44         if(judge(xx,yy)&&mp[x][y]==mp[xx][yy]){
     45             dfs(xx,yy);
     46         }            
     47     }
     48 }
     49 
     50 int bfs(int st){
     51     memset(path,-1,sizeof(path));
     52     queue<int>q;
     53     q.push(st);
     54     path[st]=0;
     55     while(!q.empty()){
     56         int k=q.front();
     57         q.pop();
     58         for(int i=0;i<v[k].size();i++){
     59             int t=v[k][i];
     60             if(path[t]==-1){
     61                 path[t]=path[k]+1;
     62                 q.push(t);
     63             }
     64         }
     65     }
     66 }
     67 
     68 int main(){
     69     FAST_IO;
     70     int t;
     71     cin>>t;
     72     while(t--){
     73         memset(vis,0,sizeof(vis));
     74         cin>>n>>m;
     75         for(int i=1;i<=n*m;i++) v[i].clear();
     76         for(int i=1;i<=n;i++){
     77             cin>>mp[i]+1;
     78         }
     79         cnt=0;
     80         //找连通块,缩点 
     81         for(int i=1;i<=n;i++){
     82             for(int j=1;j<=m;j++){
     83                 if(!vis[i][j]){
     84                     ++cnt;
     85                     dfs(i,j);
     86                 }
     87             }
     88         }
     89         //连通块间建边 
     90         for(int i=1;i<=n;i++){
     91             for(int j=1;j<=m;j++){
     92                 for(int k=0;k<4;k++){
     93                     int xx=i+d[k][0];
     94                     int yy=j+d[k][1];
     95                     if(vis[xx][yy]!=vis[i][j]){
     96                         int t1=vis[i][j],t2=vis[xx][yy];
     97                         v[t1].push_back(t2);
     98                     }
     99                 }
    100             }
    101         }
    102         //枚举每个连通块为起点,每次找出最大路径,找出这些最大路径中的最小值 
    103         int ans=INF;
    104         for(int i=1;i<=cnt;i++){
    105             bfs(i);
    106             int mmax=-INF;
    107             for(int j=1;j<=cnt;j++){
    108                 mmax=max(mmax,path[j]);
    109             }
    110             ans=min(ans,mmax);
    111         }
    112         cout<<ans<<endl;
    113     }
    114     return 0;
    115 }
  • 相关阅读:
    request和request.form和request.querystring的区别
    PL/SQL Developer连接64位Oracle
    C# Winform控件对透明图片重叠时导致图片不透明的解决方法
    C++11多线程编程-两个进程轮流打印1~100
    使用 C++11 并发编程入门
    STL vector动态扩容
    GDB入门教程
    统计整数中1的个数
    gulp的使用
    nvm安装教程
  • 原文地址:https://www.cnblogs.com/fu3638/p/9056004.html
Copyright © 2020-2023  润新知