POJ 2734 Queens, Knights and Pawns
数学模型:
已知一个n*m的国际象棋的棋盘,有qn个皇后,kn个骑士,pn的士兵(士兵不能动),士兵不能动,皇后和骑士的走法不变,求棋盘有多少格子没被占用和被皇后和骑士攻击到。
分析:
因为皇后的走法覆盖面较广,所以给每个格子设四个标记,表示是否被皇后的四个方向的攻击到,因为状态数少,可以按位标记,来整合成一个整数,分别为1,2,4,8。
View Code
#include<cstdio> #include<cstring> #define MAXN 1010 using namespace std; struct Piece { int row,col; }; Piece Q[MAXN],K[MAXN],P; int chess[MAXN][MAXN]; int jump[8][2]={{-2,-1},{-2,1},{-1,2},{1,2},{2,1},{2,-1},{1,-2},{-1,-2}}; int main() { int i,j,k,ii,jj,n,m,qn,kn,pn,t,T; for(T=1;scanf("%d%d",&n,&m),n+m;T++) { memset(chess,0,sizeof(chess)); scanf("%d",&qn); for(i=0;i<qn;i++) { scanf("%d%d",&Q[i].row,&Q[i].col); chess[Q[i].row][Q[i].col]=15; } scanf("%d",&kn); for(i=0;i<kn;i++) { scanf("%d%d",&K[i].row,&K[i].col); chess[K[i].row][K[i].col]=15; } scanf("%d",&pn); for(i=0;i<pn;i++) { scanf("%d%d",&P.row,&P.col); chess[P.row][P.col]=15; } for(qn--;qn>=0;qn--) for(k=0;k<9;k++) if(k!=4) { ii=k/3-1,jj=k%3-1; if(ii==0) t=1; else if(ii==jj) t=2; else if(jj==0) t=4; else t=8; for(i=Q[qn].row+ii,j=Q[qn].col+jj;;i+=ii,j+=jj) { if(i<1||j<1||i>n||j>m||(chess[i][j]&t)) break; chess[i][j]|=t; } } for(kn--;kn>=0;kn--) for(k=0;k<8;k++) { ii=jump[k][0]; jj=jump[k][1]; i=K[kn].row+ii,j=K[kn].col+jj; if(i<1||j<1||i>n||j>m||chess[i][j]) continue; chess[i][j]|=15; } for(i=1,k=0;i<=n;i++) for(j=1;j<=m;j++) { if(!chess[i][j]) k++; } printf("Board %d has %d safe squares.\n",T,k); } return 0; }