百科问答小站 logo
百科问答小站 font logo



在中国象棋中,最少用多少只马才能控制住整个棋盘?(马控棋盘)? 第1页

  

user avatar   zhang-ming-76-89 网友的相关建议: 
      

最少22。

只用22只马的最优解应该是260种,考虑有棋盘上下对称的结果的话就是130种。

用的是DFS+剪枝。跑了两次DFS,一次求出最优解需要用到的马的个数是22,第二次找出22只马所有可能的解。跑了一个多小时。(其实跑一次应该就可以了,懒得改了直接复制了代码里第一次的DFS= =)

主要的剪枝是考虑落子后,如果继续下去此点之前的某个点无论如何也不能控制,则返回。

代码和解法如下(只传前30种解法吧,太多了。。。

):

#include <stdio.h>

#include <memory.h>

#include <stdlib.h>


int fi,fj;

typedef struct Point{

int x;

int y;

}Point;

int check_w(int * path,int i,int j){

if((i>=0 && i<10) && (j>=0 && j<9)){

if(path[i*9+j]){

return 1;

}

}

return 0;

}


void in_reg(int ** use,Point * newp,int * newpc,int i,int j){

if((i>=0 && i<10) && (j>=0 && j<9)){

if(use[i][j]){

return;

}

newp[*newpc].x=i;

newp[*newpc].y=j;

(*newpc)++;

use[i][j]=1;

}

}

void to_use(int ** use,Point * newp,int * newpc,int i,int j){

in_reg(use,newp,newpc,i,j);

in_reg(use,newp,newpc,i-2,j-1);

in_reg(use,newp,newpc,i-1,j-2);

in_reg(use,newp,newpc,i+1,j-2);

in_reg(use,newp,newpc,i+2,j-1);

in_reg(use,newp,newpc,i-2,j+1);

in_reg(use,newp,newpc,i-1,j+2);

in_reg(use,newp,newpc,i+1,j+2);

in_reg(use,newp,newpc,i+2,j+1);

}

void dfs2path(int ** use,int usc,int * path,int minuse,int nowuse,int nowi,int nowj){

int i,j,k,l,m,newpc;

Point newP[9];

if(nowuse> minuse){

return;

}

if(usc==90){

if(nowuse== minuse){

k=0;

for(i=0;i<10;i++){

for(j=0;j<9;j++){

if(path[i*9+j]){

printf("M");

k++;

}else{

printf(".");

}

}

printf(" ");

}

printf(" ");

}

return;

}

for(i=nowi;i<10;i++){

for(j=0;j<9;j++){

if(i==nowi && j<nowj){

continue;

}

if(check_w(path,i-1,j)|| check_w(path,i+1,j)||check_w(path,i,j-1) ||check_w(path,i,j+1)){

continue;

}

if(i>nowi+4){

return;

}


for(l=0;l<i-2;l++){

for(m=0;m<9;m++){

if(!use[l][m]){

return;

}

}

}

l=i-2;

if(l>=0){

for(m=0;m<j-1;m++){

if(!use[l][m]){

return;

}

}

}

newpc=0;

to_use(use,newP,&newpc,i,j);

path[i*9+j]=1;

if(j>=8){

dfs2path(use,usc+newpc,path,minuse,nowuse+1,i+1,0);

}else{

dfs2path(use,usc+newpc,path,minuse,nowuse+1,i,j+1);

}

path[i*9+j]=0;

for(k=0;k<newpc;k++){

use[newP[k].x][newP[k].y]=0;

}

}

}

}

void dfs(int ** use,int usc,int * path,int * minuse,int nowuse,int nowi,int nowj){

int i,j,k,l,m,newpc;

Point newP[9];

if(nowuse>= *minuse){

return;

}

if(usc==90){

if(nowuse< *minuse){

*minuse=nowuse;

}

return;

}

for(i=nowi;i<10;i++){

for(j=0;j<9;j++){

if(i==nowi && j<nowj){

continue;

}

if(i>nowi+4){

return;

}

if(check_w(path,i-1,j)|| check_w(path,i+1,j)||check_w(path,i,j-1) ||check_w(path,i,j+1)){

continue;

}

for(l=0;l<i-2;l++){

for(m=0;m<9;m++){

if(!use[l][m]){

return;

}

}

}

l=i-2;

if(l>=0){

for(m=0;m<j-1;m++){

if(!use[l][m]){

return;

}

}

}

newpc=0;

to_use(use,newP,&newpc,i,j);

path[i*9+j]=1;

if(j>=8){

dfs(use,usc+newpc,path,minuse,nowuse+1,i+1,0);

}else{

dfs(use,usc+newpc,path,minuse,nowuse+1,i,j+1);

}

path[i*9+j]=0;

for(k=0;k<newpc;k++){

use[newP[k].x][newP[k].y]=0;

}

}

}

}


int main(){

int ** use,i,j,minuse,psc,usc;

int * ps;

minuse=90;

use=(int **)malloc(sizeof(int *)*10);

ps=(int *) malloc(sizeof(int)*90);

memset(ps,0,sizeof(int)*90);

for(i=0;i<10;i++){

use[i]=(int * )malloc(sizeof(int)*9);

memset(use[i],0,sizeof(int)*9);

}

dfs(use,0,ps,&minuse,0,0,0);

printf("minuse:%d ",minuse);

memset(ps,0,sizeof(int)*90);

for(i=0;i<10;i++){

memset(use[i],0,sizeof(int)*9);

}

dfs2path(use,0,ps,minuse,0,0,0);

return 0;

}






  

相关话题

  能否使用神经网络来判断奇偶数? 
  学习 Linux 有哪些好处? 
  如何长时间保存重要数据? 
  DeepMind 再登 Nature,用 AI 破译古希腊文字,该成果会对人类历史研究带来什么影响? 
  请问《计算机网络》《操作系统》《 组成原理》《 数据库》 学习的先后顺序是怎么样的,怎样学好? 
  Windows 在提示 USB 设备被占用而无法弹出时为何不指明进程名? 
  该怎么劝朋友转码? 
  程序员不需要知道太多数学,你认同吗? 
  选北大还是选港大? 
  游戏开发的编程算不算是 IT 行业中难度最大的? 

前一个讨论
如何看待用盗版 Windows 和办公软件,却在 Steam 上花了几千元买游戏的人?
下一个讨论
有哪些“不要相信歌词,他们为了押韵什么都做得出来”的例子?





© 2025-05-14 - tinynew.org. All Rights Reserved.
© 2025-05-14 - tinynew.org. 保留所有权利