zoukankan      html  css  js  c++  java
  • UVA 11214 Guarding the Chessboard 守卫棋盘(迭代加深+剪枝)

    暴力,和八皇后很像,用表示i+j和i-j标记主对角线,但是还是要加一些的剪枝的。

    1.最裸的暴搜

    6.420s,差点超时

    2.之前位置放过的就没必要在放了,每次从上一次放的位置开始放

    0.400s

    #include<cstdio>
    #include<cstring>
    
    
    const int maxn = 11;
    char G[maxn][maxn];
    int maxd;
    int n,m;
    bool visi[maxn],visj[maxn],vis1[maxn<<1],vis2[maxn<<1];
    
    
    bool dfs(int d,int si,int sj)
    {
        if(d == maxd){
            for(int i = 0; i < n; i++)
                for(int j = 0; j < m; j++){
                    if(G[i][j] == 'X'&&!visi[i]&&!visj[j]&&!vis1[i+j]&&!vis2[i-j+10])
                        return false;
                }
            return true;
        }
          for(int i = si; i < n; i++){
                for(int j = (i == si?sj:0); j < m; j++)
                if(!visi[i] || !visj[j] || !vis1[i+j]|| !vis2[i-j+10]){
                    bool f1 = visi[i], f2 = visj[j], f3 = vis1[i+j], f4 = vis2[i-j+10];
                    visi[i] = visj[j] = vis1[i+j] = vis2[i-j+10] = true;
                    if(dfs(d+1,i,j))return true;
                    visi[i] = f1; visj[j] = f2; vis1[i+j] = f3; vis2[i-j+10] = f4;
                }
    
        }
        return false;
    }
    
    
    
    int main()
    {
        int cas = 0;
        while(scanf("%d%d",&n,&m),n){
            for(int i = 0;i < n; i++) scanf("%s",G[i]);
            for(maxd = 1; maxd < 5; maxd++){
                memset(visi,0,sizeof(visi));
                memset(visj,0,sizeof(visj));
                memset(vis1,0,sizeof(vis1));
                memset(vis2,0,sizeof(vis2));
                if(dfs(0,0,0))break;
            }
            printf("Case %d: %d
    ",++cas,maxd);
        }
        return 0;
    }
    第一种剪枝

    3.可以逐行(或逐列)放置。还有一个剪枝就是最多放5个,所以maxd==4还没有解,直接输出5.

    0.201s

    #include<cstdio>
    #include<cstring>
    
    const int maxn = 11;
    char G[maxn][maxn];
    int maxd;
    int n,m;
    bool visi[maxn],visj[maxn],vis1[maxn<<1],vis2[maxn<<1];
    
    
    bool dfs(int d,int si)
    {
        if(d == maxd){
            for(int i = 0; i < n; i++)
                for(int j = 0; j < m; j++){
                    if(G[i][j] == 'X'&&!visi[i]&&!visj[j]&&!vis1[i+j]&&!vis2[i-j+10])
                        return false;
                }
            return true;
        }
          for(int i = si; i < n; i++){
                for(int j = 0; j < m; j++)
                if(!visi[i] || !visj[j] || !vis1[i+j]|| !vis2[i-j+10]){
                    bool f1 = visi[i], f2 = visj[j], f3 = vis1[i+j], f4 = vis2[i-j+10];
                    visi[i] = visj[j] = vis1[i+j] = vis2[i-j+10] = true;
                    if(dfs(d+1,i+1))return true;
                    visi[i] = f1; visj[j] = f2; vis1[i+j] = f3; vis2[i-j+10] = f4;
                }
    
        }
        return false;
    }
    
    
    
    int main()
    {
        int cas = 0;
        while(scanf("%d%d",&n,&m),n){
            for(int i = 0;i < n; i++) scanf("%s",G[i]);
            for(maxd = 1; maxd < 5; maxd++){
                memset(visi,0,sizeof(visi));
                memset(visj,0,sizeof(visj));
                memset(vis1,0,sizeof(vis1));
                memset(vis2,0,sizeof(vis2));
                if(dfs(0,0))break;
            }
            printf("Case %d: %d
    ",++cas,maxd);
        }
        return 0;
    }
  • 相关阅读:
    结算凭证中委托付款部分sql
    各公司年资金归集汇总sql
    通过开户银行账号查询客商名称 sql
    TRIGGER_15.8.3BACKUP
    备份触发器:ADDC3
    sql查询单个银行账号重复
    待研究:insert客商账户触发器增加条件提示为空
    sql:劳务统计各分公司管理费用明细合计(等同汇总报表)
    【ASP.NET程序员福利】打造一款人见人爱的ORM(二)
    【ASP.NET程序员福利】打造一款人见人爱的ORM(一)
  • 原文地址:https://www.cnblogs.com/jerryRey/p/4691532.html
Copyright © 2011-2022 走看看