Little Bishops

问题描述


A bishop is a piece used in the game of chess which is played on a board of square grids. A bishop can only move diagonally from its current position and two bishops attack each other if one is on the path of the other. In the following figure, the dark squares represent the reachable locations for bishop B1 form its current position.  The figure also shows that the bishops B1 and B2 are in attacking positions whereas B1 andB3 are not. B2 and B3 are also in non-attacking positions.

Now, given two numbers n and k, your job is to determine the number of ways one can put k bishops on an n × n chessboard so that no two of them are in attacking positions.

Input

The input file may contain multiple test cases. Each test case occupies a single line in the input file and contains two integers n(1 ≤ n ≤ 8) andk (0 ≤ k ≤ n2).

A test case containing two zeros for n and k terminates the input and you won't need to process this particular input.

Output

For each test case in the input print a line containing the total number of ways one can put the given number of bishops on a chessboard of the given size so that no two of them are in attacking positions. You may safely assume that this number will be less than 1015.


测试输入关于“测试输入”的帮助 期待的输出关于“期待的输出”的帮助 时间限制关于“时间限制”的帮助 内存限制关于“内存限制”的帮助 额外进程关于“{$a} 个额外进程”的帮助
测试用例 1 以文本方式显示
  1. 8 6↵
  2. 4 4↵
  3. 0 0↵
以文本方式显示
  1. 5599888↵
  2. 260↵
1秒 64M 0
题解思路

大致思路:

将棋盘旋转45度,然后就相当于相只可以横着或者竖着攻击,这样就跟八皇后的问题差不多,每次找到可以摆放的相的位置。然后就是一行一行的向下推,分别找到每一行可能存在的摆放情况,最后把白棋盘和黑棋盘的情况相乘就可以得到最终的结果。(白色的格子攻击不到黑色格子的相)

具体实现:

对于i行可以摆放相的位置有两种情况,一种情况是在前i-1行摆了j个相;另一种情况是在前i-1行摆了j-1个相,然后在i行摆一个相,那么在i行就可以有dp[i-1][j-1]*(c[i]-j+1)种情况。所以总和起来就是dp[i][j]=dp[i-1][j]+dp[i-1][j-1]*(c[i]-j+1),然后注意一下边界条件。

注意事项:

(1)黑白格子的行数想错1;

(2)计算每一行棋子的个数的时候需要注意,别计算错了。

摆放的相的个数应该不大于改行的棋盘个数。


实现代码


<span style="font-family:Microsoft YaHei;font-size:14px;">#include<stdio.h>  
#include<string.h>      
int dpblack[10][70], dpwrite[10][70]; 
int Black[10], Write[10];   
int main()  
{  
	long zong=0;
    int i,j,n,k,p;    
    while(scanf("%d%d",&n,&k)==2)  
    {  
    	if(n+k==0)
    	break;
    	zong=0;
    	memset(dpblack,0,sizeof(dpblack));
    	memset(dpwrite,0,sizeof(dpwrite));
        memset(Black,0,sizeof(Black));  
        memset(Write,0,sizeof(Write));  
        if(n==1)
        {
        	Black[1]=1;
        }
        if(n==2)
        {
        	Write[1]=2;
        	Black[1]=1;
        	Black[2]=1;
        }
        if(n==3)
        {
        	Write[1]=2;
        	Write[2]=2;
        	Black[1]=1;
        	Black[2]=1;
        	Black[3]=3;
        }
        if(n==4)
        {
        	Write[1]=2;
			Write[2]=2;
			Write[3]=4;	
			Black[1]=1;
			Black[2]=1;
			Black[3]=3;
			Black[4]=3;
			
        }
        if(n==5)
        {
        	Write[1]=2;
			Write[2]=2;
			Write[3]=4;
			Write[4]=4;
			Black[1]=1;
			Black[2]=1;
			Black[3]=3;
			Black[4]=3;
			Black[5]=5;
				
        }
        if(n==6)
        {
        	Write[1]=2;
			Write[2]=2;
			Write[3]=4;
			Write[4]=4;
			Write[5]=6;
			Black[1]=1;
			Black[2]=1;
			Black[3]=3;
			Black[4]=3;
			Black[5]=5;
			Black[6]=5;
			
				
        }
        if(n==7)
        {
        	Write[1]=2;
        	Write[2]=2;
        	Write[3]=4;
        	Write[4]=4;
        	Write[5]=6;
        	Write[6]=6;
        	Black[1]=1;
        	Black[2]=1;
        	Black[3]=3;
        	Black[4]=3;
        	Black[5]=5;
        	Black[6]=5;
        	Black[7]=7;
        	
        }
        if(n==8)
        {
        	Write[1]=2;
        	Write[2]=2;
        	Write[3]=4;
        	Write[4]=4;
        	Write[5]=6;
        	Write[6]=6;
        	Write[7]=8;
        	Black[1]=1;
        	Black[2]=1;
        	Black[3]=3;
        	Black[4]=3;
        	Black[5]=5;
        	Black[6]=5;
        	Black[7]=7;
        	Black[8]=7;
        	
        }  
	/*	for(p=0;p<10;p++)
		{
			printf("%d ",Write[p]);
		}	
		printf("\n");
		for(p=0;p<10;p++)
		{
			printf("%d ",Black[p]);
		}	
		printf("\n");*/	
	   // memset(dpblack,0,sizeof(dpblack));  
    	for(i=0;i<=n;i++)
		{
			 dpblack[i][0]=1;  	
		}  
    	for(i=1;i<=n;i++) 
		{
			for(j=1;j<=Black[i];j++)
			{
				dpblack[i][j]=dpblack[i-1][j]+dpblack[i-1][j-1]*(Black[i]-j+1);
			}
		}  
	//	memset(dpwrite,0,sizeof(dpwrite));  
    	for(i=0;i<=n;i++)
		{
			 dpwrite[i][0]=1;  	
		}  
    	for(i=1;i<=n;i++) 
		{
			for(j=1;j<=Write[i];j++)
			{
				dpwrite[i][j]=dpwrite[i-1][j]+dpwrite[i-1][j-1]*(Write[i]-j+1);
			}
		}   
        for (i=0;i<=k;i++)
		{
			zong+=dpblack[n][i]*dpwrite[n-1][k-i];
		}    
        printf("%ld\n",zong);  
    }  
    return 0;  
}</span>


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值