zoukankan      html  css  js  c++  java
  • HDU 4770 Lights Against Dudely(暴力+状压)

    思路:

    这个题完全就是暴力的,就是代码长了一点。

    用到了状压,因为之前不知道状压是个东西,大佬们天天说,可是我又没学过,所以对状压有一点阴影,不过这题中的状压还是蛮简单的。

    枚举所有情况,取开灯数最少的。

    解释都在注释之中了。

    #include<iostream>
    #include<algorithm>
    #include<vector>
    #include<stack>
    #include<queue>
    #include<map>
    #include<set>
    #include<cstdio>
    #include<cstring>
    #define fuck(x) cout<<#x<<" = "<<x<<endl;
    #define ls (t<<1)
    #define rs ((t<<1)+1)
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    const int maxn = 208;
    const int inf = 2.1e9;
    const ll Inf = 999999999999999999;
    const int mod = 1e9+7;
    const double eps = 1e-6;
    
    char mp[maxn][maxn];
    int vis[maxn][maxn];
    struct node
    {
        int x;
        int y;
    };
    vector<node>u;
    int get_num(int x)
    {
        int ans = 0;
        while(x){
            if(x&1){ans++;}
            x>>=1;
        }
        return ans;
    }    int n,m;
    
    int turn1(int t,int ans)
    {
        int x=u[t].x,y=u[t].y;
        if(mp[x-1][y]=='.'&&vis[x-1][y]==1){ans++;}
        if(mp[x+1][y]=='.'&&vis[x+1][y]==0){ans--;}
        if(mp[x][y+1]=='#'){return 1;}
        if(mp[x+1][y]=='#'){return 1;}
        return ans;
    }
    
    int turn2(int t,int ans)
    {
        int x=u[t].x,y=u[t].y;
        if(mp[x-1][y]=='.'&&vis[x-1][y]==1){ans++;}
        if(mp[x][y+1]=='.'&&vis[x][y+1]==1){ans++;}
        if(mp[x+1][y]=='.'&&vis[x+1][y]==0){ans--;}
        if(mp[x+1][y]=='#'){return 1;}
        if(mp[x][y-1]=='.'&&vis[x][y-1]==0){ans--;}
        if(mp[x][y-1]=='#'){return 1;}
        return ans;
    }
    
    int turn3(int t,int ans)
    {
        int x=u[t].x,y=u[t].y;
        if(mp[x][y+1]=='.'&&vis[x][y+1]==1){ans++;}
        if(mp[x][y-1]=='.'&&vis[x][y-1]==0){ans--;}
        if(mp[x-1][y]=='#'){return 1;}
        if(mp[x][y-1]=='#'){return 1;}
        return ans;
    }
    
    //判断状态是否可行
    bool light(int x)
    {
        memset(vis,0,sizeof(vis));
        int k=u.size();
        int kk[50];//kk记录有几盏灯是亮的
        for(int i=0;i<k;i++){
            if(x&1){kk[i]=1;}
            else{kk[i]=0;}
            x>>=1;
        }
        int y;
        int error=0,e;//error表示有几盏灯在没有旋转的情况下,照亮了不可照亮区域
        for(int i=0;i<k;i++){
            if(kk[i]){
                x=u[i].x;y=u[i].y;
                if(mp[x-1][y]=='#'||mp[x][y+1]=='#'){error++;e=i;}
                //vis记录某房间被照亮的次数
                vis[x-1][y]++;vis[x][y+1]++;
                vis[x][y]++;
            }
        }
        if(error>1){return false;}
        int num=0;//num记录有几个区域,应该被照亮而没有被照亮。
        
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                if(mp[i][j]=='.'&&!vis[i][j]){num++;}
                if(mp[i][j]=='#'&&vis[i][j]>1){return false;}
            }
        }
        if(num>2){return false;}
        //tt是num的中间结果
        int tt;
        if(error){
            //turn 表示旋转,返回值其实是旋转之后满不满足题意
            tt=turn1(e,num);if(tt==0){return true;}
            tt=turn2(e,num);if(tt==0){return true;}
            tt=turn3(e,num);if(tt==0){return true;}
            return false;
        }
        if(num==0){return true;}
        for(int i=0;i<k;i++){
            if(kk[i]){
                tt=turn1(i,num);if(tt==0){return true;}
                tt=turn2(i,num);if(tt==0){return true;}
                tt=turn3(i,num);if(tt==0){return true;}
            }
        }
        return false;
    }
    
    int main()
    {
        while(scanf("%d%d",&n,&m)!=EOF&&(n!=0&&m!=0)){
            memset(mp,0,sizeof(mp));
            for(int i=1;i<=n;i++){
                scanf("%s",mp[i]+1);
            }
            memset(vis,0,sizeof(vis));
            u.clear();
            for(int i=1;i<=n;i++){
                for(int j=1;j<=m;j++){
                    if(mp[i][j]=='.'){
                        u.push_back(node{i,j});
                    }
                }
            }
            int siz = u.size();
            int k=(1<<siz);
            int num;
            int ans = inf;
            for(int i=0;i<k;i++){
                num=get_num(i);
                if(num>=ans){continue;}
                if(light(i))ans=min(ans,num);
            }
            if(ans==inf){ans=-1;}
            printf("%d
    ",ans);
        }
    
        return 0;
    }
  • 相关阅读:
    IdentityServer4 突然登录就不香了?SameSite?
    11111
    搭建ASP.NET Core API框架(1) 从零开始
    搭建ASP.NET WEB API框架(3) 内核数据库
    搭建VUE项目框架(2) 创建项目
    搭建ASP.NET WEB API框架(2) 创建项目
    搭建ASP.NET WEB API框架(1) 从零开始
    搭建ASP.NET MVC5框架(2) 创建项目
    搭建VUE项目框架(1) 从零开始
    搭建ASP.NET MVC5框架(1) 从零开始
  • 原文地址:https://www.cnblogs.com/ZGQblogs/p/9762130.html
Copyright © 2011-2022 走看看