• N Queen Again LightOJ


    N Queen Again LightOJ - 1061

    首先预处理(或打表)出所有八皇后的解法(只有92种)。然后枚举目标状态,对于每一个目标状态用一个状压dp求出到达那个状态的最小费用。到达任何一个目标状态的最小费用就是答案。

    显然,已知原来8个点的位置,要到达目标8个点的位置,就是使得每一个原来点匹配一个目标点。(为什么看到就想到爆搜?然而有比爆搜更好的..)

    状压dp是:

    ans[S]表示用[满足(编号被包含在S集合中)条件的所有目标点]去匹配原来点中的前 |S| (表示S集合的点的个数)个点的最小费用。

    对于每一个枚举出的S,此时需要被匹配的点就是原来点的第 |S| 个,那么枚举从S中选择一个目标点去匹配它,记录最小的费用。

    对于每一步的费用,有一个直觉做法:

    如果原来点和目标点在同一位置,那么费用为0。否则如果在同一列或同一斜线,那么费用为1。否则费用为2。

    然而这个直觉做法,在想出来之后很可能会下意识就否定掉,由于可能有已经摆好的或未摆好的棋子挡路。

    然而事实上是对的:(如果不对这题就没法做了吧..)http://blog.csdn.net/xiefubao/article/details/25276999

    (所以说..还是要大胆猜想,暴力对拍吗....感觉某些这种猜想,提出一个看上去正确的证明,都有可能遗漏了什么呢..所以即使想出了一个证明也不一定敢用猜想)

    (这题根本没办法暴力对拍呢...所以还是要抱着对自己证明的信任?)

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 int pre_ans[100][9],num_pre;
     6 bool vis[9],vis2[100],vis3[100];
     7 int t1[9],t2[9],len;
     8 int T,TT,now,anss,cnt;
     9 int ans[300];
    10 void pre_dfs(int x)
    11 {
    12     if(x>8)
    13     {
    14         ++num_pre;
    15         memcpy(pre_ans[num_pre],t1,sizeof(t1));
    16         return;
    17     }
    18     int i;
    19     for(i=1;i<=8;i++)
    20         if(!vis[i]&&!vis2[x-i+50]&&!vis3[x+i])
    21         {
    22             vis[i]=1;
    23             vis2[x-i+50]=1;
    24             vis3[x+i]=1;
    25             t1[x]=i;
    26             pre_dfs(x+1);
    27             vis[i]=0;
    28             vis2[x-i+50]=0;
    29             vis3[x+i]=0;
    30         }
    31 }
    32 int get_dis(int a,int b)
    33 {
    34     if(a==t1[b]&&pre_ans[now][a]==t2[b])    return 0;
    35     if(a==t1[b])    return 1;
    36     if(pre_ans[now][a]==t2[b])    return 1;
    37     if(a+pre_ans[now][a]==t1[b]+t2[b])    return 1;
    38     if(a-pre_ans[now][a]==t1[b]-t2[b])    return 1;
    39     return 2; 
    40 }
    41 int main()
    42 {
    43     int i,j;
    44     char c;
    45     pre_dfs(1);
    46     scanf("%d",&T);
    47     for(TT=1;TT<=T;TT++)
    48     {
    49         len=0;anss=0x3f3f3f3f;
    50         for(i=1;i<=8;i++)
    51             for(j=1;j<=8;j++)
    52             {
    53                 c=getchar();
    54                 while(c!='.'&&c!='q')    c=getchar();
    55                 if(c=='q')
    56                 {
    57                     ++len;
    58                     t1[len]=i;
    59                     t2[len]=j;
    60                 }
    61             }
    62         for(now=1;now<=num_pre;now++)
    63         {
    64             memset(ans,0x3f,sizeof(ans));
    65             ans[0]=0;
    66             for(i=1;i<(1<<8);i++)
    67             {
    68                 cnt=__builtin_popcount(i);
    69                 for(j=1;j<=8;j++)
    70                     if(i&(1<<(j-1)))
    71                         ans[i]=min(ans[i],ans[i^(1<<(j-1))]+get_dis(j,cnt));
    72             }
    73             anss=min(anss,ans[(1<<8)-1]);
    74         }
    75         printf("Case %d: %d
    ",TT,anss);
    76     }
    77 }
  • 相关阅读:
    DRF分页器
    DRF版本控制
    crrm复习
    python面试题网络编程和数据库
    python基础面试题
    前端格式
    数据库基本命令
    数据库管理系统
    线程协程和进程
    IPC通信
  • 原文地址:https://www.cnblogs.com/hehe54321/p/loj-1061.html
Copyright © 2020-2023  润新知