在中国象棋中,马是走日字的。一个马的管辖范围指的是当前位置以及一步之内能走到的位置,下图的绿色旗子表示马能走到的位置。
如果一匹马的某个方向被蹩马脚,它就不能往这个方向跳了,如下图所示,海星的位置存在旗子,马就不能往上跳到那两个位置了:
那么问题来了,在一个 n\times mn×m 的棋盘内,如何用最少的马管辖住所有 n\times mn×m 个格子。比如 n=m=3n=m=3 时,最少要用 55 只马才能管辖所有棋盘,一种可能的方案如下:
当 n=m=5n=m=5 时,请你求出用最少马管辖的 方案个数。
样例输入复制
无
样例输出复制
无
题目来源
题目解答:
用二进制2^25次方枚举所有马的摆放情况,对每一种情况,判断是否都管辖即可。注意细节。
代码:
#include <iostream>
#include <cstring>
#include <algorithm>
#include <stack>
#include <vector>
#include <cstdio>
#include <map>
#define LL long long
#define INF 0x3f3f3f3f
using namespace std;
const int maxn=6;
int n,m,len,sum,mini;
int mapp[maxn][maxn];
bool book[maxn][maxn];
int dx[4][2]={-2,-2,2,2,-1,1,-1,1};
int dy[4][2]={1,-1,1,-1,2,2,-2,-2};
int px[4]={-1,1,0,0};
int py[4]={0,0,1,-1};
bool check(int x,int y)
{
if(x<0||y<0||x>=n||y>=m)
return false;
return true;
}
bool judge()
{
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
if(!book[i][j])
return false;
}
}
return true;
}
int main()
{
n=m=5;
len=n*m;
sum=0;
mini=2*len;
for(int i=1;i<(1<<len);i++)
{
int cnt=0;
memset(mapp,0,sizeof(mapp));
memset(book,false,sizeof(book));
int cnz=0;
for(int j=i;j>0;j>>=1)
{
if(j&1)
{
mapp[cnt/5][cnt%5]=1;
book[cnt/5][cnt%5]=true;
cnz++;
}
cnt++;
}
if(cnz>mini)
continue;
for(int u=0;u<n;u++)
{
for(int v=0;v<m;v++)
{
if(mapp[u][v]==1)
{
for(int z=0;z<4;z++)
{
int tx=u+px[z];
int ty=v+py[z];
if(check(tx,ty)&&mapp[tx][ty]==0)
{
for(int j=0;j<2;j++)
{
int zx=u+dx[z][j];
int zy=v+dy[z][j];
if(check(zx,zy)&&book[zx][zy]==false&&mapp[zx][zy]==0)
{
book[zx][zy]=true;
}
}
}
}
}
}
}
if(judge())
{
if(cnz<mini)
{
mini=cnz;
sum=1;
}
else if(cnz==mini)
{
sum++;
}
}
}
cout << mini << ' ' << sum << endl;
return 0;
}