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());
    }
}
原文地址:https://www.cnblogs.com/bxd123/p/10414860.html