zoukankan      html  css  js  c++  java
  • 7-10 守卫棋盘 uva11214

    输入要给n*m的棋盘  均小于10   某些格子有标记  用最少的皇后  辐射到所有的标记

    限时 6666ms

    用IDA*    时间6000  尴尬。

    #include<bits/stdc++.h>
    using namespace std;
    #define N 10
    int n,m;
    int mp[N][N];
    int cnt;
    int visn[N];
    int vism[N];
    int visx[2*N];
    
    bool dfs(int d,int maxx)
    {
        if(cnt==0)return true;
        if(d==maxx)return false;
        if( (maxx-d)*( 3*n+m-3  )  <cnt )return false;//毫无用处。。
    
        int oldmap[N][N];//一定要开到里面  一开始开到外面错了!
        memcpy(oldmap,mp,sizeof mp);
        int oldcnt=cnt;
        for(int i=1;i<=n;i++)
            if(!visn[i])
          for(int j=1;j<=m;j++)
            if(!vism[j])
          {
              visn[i]=vism[j]=visx[i+j]=1;
              for(int k=1;k<=n;k++)
                 if(mp[k][j])cnt--,mp[k][j]=0;
              for(int k=1;k<=m;k++)
                  if(mp[i][k])cnt--,mp[i][k]=0;
              for(int k=1;k<=n;k++)
                for(int s=1;s<=m;s++)
               {
                   if( (s-k)==(j-i)||(s+k)==(i+j) )
                    if(mp[k][s]) mp[k][s]=0,cnt--;
               }
                if(cnt!=oldcnt)
                if(dfs(d+1,maxx))return true;
              memcpy(mp,oldmap,sizeof mp);
              cnt=oldcnt;
              visn[i]=vism[j]=0;
          }
      return false;
    }
    
    int solve()
    {
        if(cnt==0)return 0;
         for(int maxx=1;;maxx++){
            memset(visn,0,sizeof visn);
            memset(vism,0,sizeof vism);
            if(dfs(0,maxx) )return maxx;
         }
    }
    
    int main()
    {
        int cas=0;
        while(scanf("%d",&n),n)
        {    cnt=0;
            scanf("%d",&m);getchar();
            char ch;
            for(int i=1;i<=n;i++)
            {
            for(int j=1;j<=m;j++)
            {
                scanf("%c",&ch);
                if(ch=='X')mp[i][j]=1,cnt++;
            }
            getchar();
            }
            printf("Case %d: %d
    ",++cas,solve());
        }
    }

    每次dfs都要扫面落子的四个方位实在太费时间 真的铁脑残

    应该像八皇后问题那样  设置标记数组就好了!! 900ms

    #include<bits/stdc++.h>
    using namespace std;
    #define N 10
    int n,m;
    int mp[N][N];
    int cnt;
    int visn[N];
    int vism[N];
    int visx[3*N];
    int visy[3*N];
    
    bool judge()
    {
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                if(mp[i][j]&&!visn[i]&&!vism[j]&&!visx[i+j]&&!visy[i-j+10])return false;
    
        return true;
    
    }
    
    bool dfs(int d,int maxx)
    {
        if(judge())return true;
        if(d==maxx)return false;
      
        for(int i=1;i<=n;i++)
            if(!visn[i])
          for(int j=1;j<=m;j++)
            if(!vism[j])
          {
              visn[i]=vism[j]=1;
              int a=visx[i+j], b=visy[i-j+10];
              visx[i+j]=visy[i-j+10]=1;
    
                if(dfs(d+1,maxx))return true;
              visn[i]=vism[j]=0;
              visx[i+j]=a;visy[i-j+10]=b;
          }
      return false;
    }
    
    int solve()
    {
        if(cnt==0)return 0;
         for(int maxx=1;;maxx++){
            memset(visn,0,sizeof visn);
            memset(vism,0,sizeof vism);
            memset(visx,0,sizeof visx);
            memset(visy,0,sizeof visy);
            if(dfs(0,maxx) )return maxx;
         }
    }
    
    int main()
    {
        int cas=0;
        while(scanf("%d",&n),n)
        {    cnt=0;
            scanf("%d",&m);getchar();
            char ch;
            for(int i=1;i<=n;i++)
            {
            for(int j=1;j<=m;j++)
            {
                scanf("%c",&ch);
                if(ch=='X')mp[i][j]=1,cnt++;
                else mp[i][j]=0;
            }
            getchar();
            }
            printf("Case %d: %d
    ",++cas,solve());
        }
    }

    对行数进行优化  使行数升序:90ms 可以保证没有重复 !!!  上面那个代码有很多重复

    #include<bits/stdc++.h>
    using namespace std;
    #define N 10
    #define maxn 12
    int n,m;
    int mp[N][N];
    int cnt;
    int visn[N];
    int vism[N];
    int visx[3*N];
    int visy[3*N];
    int maxx;
    bool judge()
    {
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                if(mp[i][j]&&!visn[i]&&!vism[j]&&!visx[i+j]&&!visy[i-j+10])return false;
        return true;
    }
    
    bool dfs(int d,int raw)
    {
        if(judge())return true;
        if(d==maxx)return false;
    
        for(int i=raw;i<=n;i++)
          for(int j=1;j<=m;j++)
          {
              int c=visn[i],d1=vism[j],a=visx[i+j], b=visy[i-j+10];
    
              visx[i+j]=visy[i-j+10]=visn[i]=vism[j]=1;
    
                if(dfs(d+1,i+1))return true;
    
              visn[i]=c,vism[j]=d1;
              visx[i+j]=a;visy[i-j+10]=b;
          }
      return false;
    }
    
    int solve()
    {
         for( maxx=0;;maxx++){
            memset(visn,0,sizeof visn);
            memset(vism,0,sizeof vism);
            memset(visx,0,sizeof visx);
            memset(visy,0,sizeof visy);
            if(dfs(0,1) )return maxx;
         }
    }
    
    int main()
    {
        int cas=0;
        while(scanf("%d",&n),n)
        {
            scanf("%d",&m);getchar();
            char ch;
            for(int i=1;i<=n;i++)
            {
            for(int j=1;j<=m;j++)
            {
                scanf("%c",&ch);
                if(ch=='X')mp[i][j]=1;
                else mp[i][j]=0;
            }
            getchar();
            }
            printf("Case %d: %d
    ",++cas,solve());
        }
    }
  • 相关阅读:
    nginx解决跨域问题
    SSM整合相关试题
    SSM整合案例--用户登录
    非法用户登录拦截
    SpringMVC拦截器和数据校验
    SpringMVC文件上传
    SpringMVC异常处理
    SpringMVC方法的返回值类型和自动装配
    SpringMVC
    spring和mybatis整合
  • 原文地址:https://www.cnblogs.com/bxd123/p/10414860.html
Copyright © 2011-2022 走看看