棋盘上的问题

子曰:“吾尝终日不食、

终夜不寝以思,无益,不如学也。”

孔子说:"我曾经常终日不吃饭,整夜不睡觉来思考,没有长进,不如学习."

本文讲述了棋盘上的问题.

首先,我们要亮相的是大家都知道的问题,著名的八皇后问题!

高斯大佬好像求错了,他认为有76种.但是他是手算的,人无完人,金无赤足.

皇后的攻击范围

在这个问题上,我们使用状态压缩集合的技巧。

虽然我们是通过搜索的形式,但是我们赋予其递推的意义,

运用数学的表述形式,描述了程序.

#include<bits/stdc++.h>using namespace std;int ans;int n;void dfs(int now,int col,int dia,int rev_dia){  if(now==n)  {    ans++;    return ;  }  for(int i=0;i<n;i++)  {    if(col>>i&1)    {      continue;    }    int now_dia=now-i+n-1;    if(dia>>now_dia&1)continue;    int now_rev_dia=i+now;    if(rev_dia>>now_rev_dia&1)continue;    dfs(now+1,col|(1<<i),dia|(1<<now_dia),rev_dia|(1<<now_rev_dia));  }}signed main(){  n=8;  dfs(0,0,0,0);  cout<<ans;}

那么怎没知道pre和now是相容的?

我们提前将满足一行的国王摆法,安排好。

同时,将每一个now的前面可以转移的状态枚举出来。

这是一个双马问题,在一个n×n的棋盘上,有多少种放两个马的方法。

但是马的放置是没有顺序的,通过乘法原理,消除顺序。

#include<bits/stdc++.h>using namespace std;#define int long long int solve(int n){  int ans=0;  if(n==1)return 0;  if(n==2)return 6;  if(n==3)return 28;  if(n==4)return 96;  if(n==5)return 252;  if(n==6)return 550;  ans=(n-4)*(n-4)*(n*n-9);  ans+=(n-4)*4*(n*n-6-1);  ans+=4*(n*n-5);  ans+=8*(n*n-4);  ans+=4*(n-4)*(n*n-5);  ans+=4*(n*n-3);  return ans/2;}signed main(){  int n;  cin>>n;  for(int i=1;i<=n;i++)  cout<<solve(i)<<"\n";}

接下来的就是跳马问题,

有没有可能,这个马将格子跳一次,并且只有一次?

这道题是典型的哈密顿回路问题。
我们还是使用搜索的方式。

#include<bits/stdc++.h>using namespace std;#define int long longint n,m;const int N=1010;int dx[]={-1,-1,1,1,2,2,-2,-2};int dy[]={2,-2,2,-2,1,-1,1,-1};int vis[N][N]; bool check(int x,int y){  return x>=0&&x<n&&y<m&&y>=0;}void dfs(int x,int y,int cnt){  if(cnt==n*m)  {    for(int i=0;i<n;i++)    {      for(int j=0;j<m;j++)      cout<<vis[i][j]<<" ";      cout<<"\n";    }    exit(0);  }  for(int i=0;i<8;i++)  {    int xx=dx[i]+x;    int yy=dy[i]+y;    if(!check(xx,yy))    {      continue;    }    if(vis[xx][yy])continue;    vis[xx][yy]=cnt;    dfs(xx,yy,cnt+1);    vis[xx][yy]=0;  }}signed main(){  n=4;  m=8;  dfs(0,0,1);  cout<<"NO";}

当然也可以是状态压缩.

#include<bits/stdc++.h>using namespace std;#define int long long int n,m;const int N=1010;int   dx[]={-1,-1,1,1,2,2,-2,-2};int  dy[]={2,-2,2,-2,1,-1,1,-1};map<int,int>f[20][20];bool check(int x,int y){  return x>=0&&x<n&&y>=0&&y<m;}void print(int x){  for(int i=32;i>=0;i--)  {    if(x>>i&1)    cout<<1;    else cout<<0;  }  cout<<"\n";}bool dfs(int x,int y,int st){//  cout<<x<<" "<<y<<" ";//  cout<<st<<"\n";  //print(st);  if(st==(1ll<<(n*m))-1)  {    return true;  }  if(f[x][y].count(st))  {    return f[x][y][st];  }  bool res=0;  for(int i=0;i<8;i++)  {    int xx=x+dx[i];    int yy=y+dy[i];    if(!check(xx,yy))continue;    if((st>>(xx*m+yy))&1)continue;    //    if((st|(1ll<<(xx*m+yy)))<0)//1ll<< 1ll<< int 右移动太小,因该1ll<< //    {//      cout<<"\n";//      print(1ll<<(xx*m+yy));//      cout<<(1ll<<(xx*m+yy))<<"\n";//      cout<<x<<" "<<y<<" ";//      print(st);//      cout<<" "<<xx<<" "<<yy<<"\n";//      exit(0);//    }    res|=dfs(xx,yy,st|(1ll<<(xx*m+yy)));    if(res)break;  }  return f[x][y][st]=res;}signed main(){  n=4,m=3;  cout<<dfs(0,0,1);}

只是可能加速效果不是很出色.

并且状态的空间增量特别大.

8×8跳马的一种方案

  • 6
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值