原题:
题意:
n*m的棋盘用最少个马管住(放马的位置,马可以打到的位置),问这个数量。
解析:
dfs,每个位置三种状态:
- 0:可以放置
- 1:不可放置
- 2:已经放置
主要是别马脚的问题,如果有个点没有被放置,它需要被另一个点管住,那么这个路上不能有马脚。
#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(register int i=a;i<=b;i++)
int read(){ int ans=0; char last=' ',ch=getchar();
while(ch<'0' || ch>'9')last=ch,ch=getchar();
while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
if(last=='-')ans=-ans; return ans;
}
int Map[6][6];
int n,m;
int di[8][2]={{1,2},{1,-2},{-1,2},{-1,-2},{2,1},{-2,-1},{-2,1},{2,-1}};
int dii[8][2]={{1,1},{1,-1},{-1,1},{-1,-1},{1,1},{-1,-1},{-1,1},{1,-1}};
int ans;
void out(){
printf("out\n");
rep(i,1,n){
rep(j,1,m){
printf("%d ",Map[i][j]);
}
printf("\n");
}
printf("\n");
}
void dfs(const int x,const int y,int use){
if(use>=ans)return;
if(x>n){if(ans>use)ans=use;return;}
if(Map[x][y]==2)
return dfs((y==m?x+1:x),(y==m?1:y+1),use);
if(Map[x][y]==0){
// 填
Map[x][y]=2;
dfs((y==m?x+1:x),(y==m?1:y+1),use+1);
Map[x][y]=0;
}
// 不填
int can=0;
rep(i,0,7){
int xx=x+di[i][0],yy=y+di[i][1];
int jx=x+dii[i][0],jy=y+dii[i][1];
if(xx<1||xx>n||yy<1||yy>m||Map[xx][yy]!=2||Map[jx][jy]==2)continue;
can=1;
int tmp=Map[jx][jy];
Map[jx][jy]=1;
dfs((y==m?x+1:x),(y==m?1:y+1),use);
Map[jx][jy]=tmp;
}
if(can)return;
rep(i,0,7){
int xx=x+di[i][0],yy=y+di[i][1];
int jx=x+dii[i][0],jy=y+dii[i][1];
if(xx<1||xx>n||yy<1||yy>m||Map[jx][jy]==2)continue;
//被限制或已填
if(Map[xx][yy])continue;
Map[xx][yy]=2;
int tmp=Map[jx][jy];
Map[jx][jy]=1;
dfs((y==m?x+1:x),(y==m?1:y+1),use+1);
Map[xx][yy]=0;
Map[jx][jy]=tmp;
}
}
int Ans[6][6];
int main(){
int t=read();
while(t--){
n=read(),m=read();
if(Ans[n][m]){
printf("%d\n",Ans[n][m]);
continue;
}
memset(Map,0,sizeof Map);
ans=1e9;
dfs(1,1,0);
Ans[n][m]=ans;
printf("%d\n",ans);
}
}