找回密码
 欢迎注册
楼主: mathe

[擂台] 中国象棋马控制棋盘问题

[复制链接]
发表于 2010-8-8 09:11:09 | 显示全部楼层
第ii)问也存在上限问题:最多能放多少只马,使得不至于因阻塞而产生盲点。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2010-8-8 11:37:15 | 显示全部楼层
的确,实际上问题1也有上限问题。 关于问题i),现在通过计算机已经能够解决了,只是耗用资源比较大,建议在有2G以上物理内存的计算机上运行:
  1. // cs.cpp : Defines the entry point for the console application.
  2. //
  3. #include "stdafx.h"
  4. #include <ctype.h>
  5. #include <algorithm>
  6. using namespace std;
  7. #define NS 47065889
  8. char st[18];
  9. char init[9];
  10. int tc=0;
  11. long long sl[NS];
  12. char bs[9][NS];
  13. long long cc1[NS];
  14. long long cc2[NS];
  15. long long *cp1,*cp2;
  16. #define HASKNIGHT 2
  17. #define ATTACKED 1
  18. #define NOTATTACKED 0
  19. //#define DUMP_DATA
  20. #define ENUM_ALL
  21. #ifdef ENUM_ALL
  22. void show(int index, bool bothline=false)
  23. {
  24. int i;
  25. for(i=0;i<9;i++){
  26. switch((sl[index]>>(2*i+18))&3){
  27. case HASKNIGHT:
  28. printf("N");
  29. break;
  30. case ATTACKED:
  31. case NOTATTACKED:
  32. printf("*");
  33. break;
  34. }
  35. }
  36. printf("\n");
  37. if(bothline){
  38. for(i=0;i<9;i++){
  39. switch((sl[index]>>(2*i))&3){
  40. case HASKNIGHT:
  41. printf("N");
  42. break;
  43. case ATTACKED:
  44. case NOTATTACKED:
  45. printf("*");
  46. break;
  47. }
  48. }
  49. printf("\n");
  50. }
  51. }
  52. void dump(int line, int index)
  53. {
  54. int c;
  55. char st[18];
  56. show(index);
  57. c=bs[line][index];
  58. int i,j,k,bc;
  59. for(i=0;i<NS;i++){
  60. if(bs[line-1][i]==0)continue;
  61. for(j=0;j<18;j++){
  62. st[j]=(sl[i]>>(2*j))&3;
  63. }
  64. for(j=0;j<512;j++){
  65. bc=0;
  66. for(k=0;k<9;k++)if((j&(1<<k))!=0)bc++;
  67. int nc=bs[line-1][i]+bc;
  68. if(nc!=c)
  69. continue;
  70. for(k=0;k<9;k++){
  71. if(st[k]==NOTATTACKED){
  72. int p=0;
  73. if(k>=1&&st[k+9-1]!=HASKNIGHT&&(j&(1<<(k-1)))!=0)p=1;
  74. if(k<8&&st[k+9+1]!=HASKNIGHT&&(j&(1<<(k+1)))!=0)p=1;
  75. if(p==0)break;
  76. }
  77. }
  78. if(k<9)continue;
  79. long long x=0LL;
  80. for(k=0;k<9;k++){
  81. int ns=st[k+9];
  82. if(ns==NOTATTACKED){
  83. int p=0;
  84. if(k>=2&&(j&(1<<(k-1)))==0&&(j&(1<<(k-2)))!=0)p=1;
  85. if(k<7&&(j&(1<<(k+1)))==0&&(j&(1<<(k+2)))!=0)p=1;
  86. if(p)ns=ATTACKED;
  87. }
  88. x|=((long long)ns)<<(2*k);
  89. }
  90. for(k=0;k<9;k++){
  91. int ns;
  92. if((j&(1<<k))!=0)ns=HASKNIGHT;
  93. else ns=0;
  94. if(ns==0){
  95. int p=0;
  96. if(k>=1&&st[k+9-1]!=HASKNIGHT&&st[k-1]==HASKNIGHT)p=1;
  97. if(k<8&&st[k+9+1]!=HASKNIGHT&&st[k+1]==HASKNIGHT)p=1;
  98. if(k>=2&&(st[k+9-1]!=HASKNIGHT)&&st[k+9-2]==HASKNIGHT)p=1;
  99. if(k<7&&(st[k+9+1]!=HASKNIGHT)&&st[k+9+2]==HASKNIGHT)p=1;
  100. if(p==1)ns=1;
  101. }
  102. x|=((long long)ns)<<(2*k+18);
  103. }
  104. if(x!=sl[index])
  105. continue;
  106. if(line>1)
  107. dump(line-1,i);
  108. else{
  109. show(i,true);
  110. }
  111. return;
  112. }
  113. }
  114. }
  115. void update_cp(int line)
  116. {
  117. int i,j,k,bc;
  118. for(i=0;i<NS;i++){
  119. if(bs[line-1][i]==0)continue;
  120. for(j=0;j<18;j++){
  121. st[j]=(sl[i]>>(2*j))&3;
  122. }
  123. for(j=0;j<512;j++){
  124. bc=0;
  125. for(k=0;k<9;k++)if((j&(1<<k))!=0)bc++;
  126. for(k=0;k<9;k++){
  127. if(st[k]==NOTATTACKED){
  128. int p=0;
  129. if(k>=1&&st[k+9-1]!=HASKNIGHT&&(j&(1<<(k-1)))!=0)p=1;
  130. if(k<8&&st[k+9+1]!=HASKNIGHT&&(j&(1<<(k+1)))!=0)p=1;
  131. if(p==0)break;
  132. }
  133. }
  134. if(k<9)continue;
  135. long long x=0LL;
  136. for(k=0;k<9;k++){
  137. int ns=st[k+9];
  138. if(ns==NOTATTACKED){
  139. int p=0;
  140. if(k>=2&&(j&(1<<(k-1)))==0&&(j&(1<<(k-2)))!=0)p=1;
  141. if(k<7&&(j&(1<<(k+1)))==0&&(j&(1<<(k+2)))!=0)p=1;
  142. if(p)ns=ATTACKED;
  143. }
  144. x|=((long long)ns)<<(2*k);
  145. }
  146. for(k=0;k<9;k++){
  147. int ns;
  148. if((j&(1<<k))!=0)ns=HASKNIGHT;
  149. else ns=0;
  150. if(ns==0){
  151. int p=0;
  152. if(k>=1&&st[k+9-1]!=HASKNIGHT&&st[k-1]==HASKNIGHT)p=1;
  153. if(k<8&&st[k+9+1]!=HASKNIGHT&&st[k+1]==HASKNIGHT)p=1;
  154. if(k>=2&&(st[k+9-1]!=HASKNIGHT)&&st[k+9-2]==HASKNIGHT)p=1;
  155. if(k<7&&(st[k+9+1]!=HASKNIGHT)&&st[k+9+2]==HASKNIGHT)p=1;
  156. if(p==1)ns=1;
  157. }
  158. x|=((long long)ns)<<(2*k+18);
  159. }
  160. int nc=bs[line-1][i]+bc;
  161. if(nc>127)nc=127;
  162. long long *p=lower_bound(sl,sl+NS,x);
  163. if(p==NULL||p>=sl+NS)continue;
  164. int index = p-sl;
  165. if(bs[line][index]==nc){
  166. cp2[index]+=cp1[index];
  167. }
  168. }
  169. }
  170. }
  171. void nextline(int line)
  172. {
  173. int i,j,k,bc;
  174. for(i=0;i<NS;i++){
  175. if(bs[line-1][i]==0)continue;
  176. for(j=0;j<18;j++){
  177. st[j]=(sl[i]>>(2*j))&3;
  178. }
  179. for(j=0;j<512;j++){
  180. bc=0;
  181. for(k=0;k<9;k++)if((j&(1<<k))!=0)bc++;
  182. for(k=0;k<9;k++){
  183. if(st[k]==NOTATTACKED){
  184. int p=0;
  185. if(k>=1&&st[k+9-1]!=HASKNIGHT&&(j&(1<<(k-1)))!=0)p=1;
  186. if(k<8&&st[k+9+1]!=HASKNIGHT&&(j&(1<<(k+1)))!=0)p=1;
  187. if(p==0)break;
  188. }
  189. }
  190. if(k<9)continue;
  191. long long x=0LL;
  192. for(k=0;k<9;k++){
  193. int ns=st[k+9];
  194. if(ns==NOTATTACKED){
  195. int p=0;
  196. if(k>=2&&(j&(1<<(k-1)))==0&&(j&(1<<(k-2)))!=0)p=1;
  197. if(k<7&&(j&(1<<(k+1)))==0&&(j&(1<<(k+2)))!=0)p=1;
  198. if(p)ns=ATTACKED;
  199. }
  200. x|=((long long)ns)<<(2*k);
  201. }
  202. for(k=0;k<9;k++){
  203. int ns;
  204. if((j&(1<<k))!=0)ns=HASKNIGHT;
  205. else ns=0;
  206. if(ns==0){
  207. int p=0;
  208. if(k>=1&&st[k+9-1]!=HASKNIGHT&&st[k-1]==HASKNIGHT)p=1;
  209. if(k<8&&st[k+9+1]!=HASKNIGHT&&st[k+1]==HASKNIGHT)p=1;
  210. if(k>=2&&(st[k+9-1]!=HASKNIGHT)&&st[k+9-2]==HASKNIGHT)p=1;
  211. if(k<7&&(st[k+9+1]!=HASKNIGHT)&&st[k+9+2]==HASKNIGHT)p=1;
  212. if(p==1)ns=1;
  213. }
  214. x|=((long long)ns)<<(2*k+18);
  215. }
  216. int nc=bs[line-1][i]+bc;
  217. if(nc>127)nc=127;
  218. long long *p=lower_bound(sl,sl+NS,x);
  219. if(p==NULL||p>=sl+NS)continue;
  220. int index = p-sl;
  221. if(bs[line][index]==0||bs[line][index]>nc){
  222. bs[line][index]=nc;
  223. }
  224. }
  225. }
  226. printf("Finished line %d\n",line+1);
  227. }
  228. #define BEST_COUNT 22
  229. void countall()
  230. {
  231. long long *p;
  232. cp1=cc1,cp2=cc2;
  233. int i,j;
  234. for(i=0;i<NS;i++){
  235. for(j=0;j<18;j++){
  236. if(((sl[i]>>(2*j))&3)==0)
  237. break;
  238. }
  239. if(j<18)continue;
  240. if(bs[8][i]!=BEST_COUNT)continue;
  241. cp1[i]=1LL;
  242. }
  243. for(i=8;i>=1;i--){
  244. update_cp(i);
  245. p=cp2;
  246. cp2=cp1;
  247. cp1=p;
  248. long long tsize=0ll;
  249. for(j=0;j<NS;j++)tsize+=cp2[j];
  250. printf("Total count %lld in step %d\n",tsize,i);
  251. memset(cp2,0,sizeof(cp2[0])*NS);
  252. }
  253. }
  254. int findbestlast()
  255. {
  256. int i,j;
  257. int bc=0;
  258. int index;
  259. for(i=0;i<NS;i++){
  260. for(j=0;j<18;j++){
  261. if(((sl[i]>>(2*j))&3)==0)
  262. break;
  263. }
  264. if(j<18)continue;
  265. if(bs[8][i]==0)continue;
  266. if(bc==0||bs[8][i]<bc){
  267. bc=bs[8][i];
  268. index=i;
  269. }
  270. }
  271. printf("best value %d\n",bc);
  272. dump(8,index);
  273. return bc;
  274. }
  275. void init2()
  276. {
  277. int i,j;
  278. for(i=0;i<tc;i++){
  279. int c2=0;
  280. for(j=0;j<18;j++){
  281. st[j]=(sl[i]>>(2*j))&3;
  282. if(st[j]==2)c2++;
  283. }
  284. for(j=0;j<9;j++){
  285. if(st[j]==ATTACKED){
  286. int p=0;
  287. if(j>=2&&st[9+j-2]==HASKNIGHT&&st[9+j-1]!=HASKNIGHT)
  288. p=1;
  289. if(j<7&&st[9+j+2]==HASKNIGHT&&st[9+j+1]!=HASKNIGHT)
  290. p=1;
  291. if(p==0)break;
  292. }
  293. }
  294. if(j<9){
  295. continue;
  296. }
  297. for(j=0;j<9;j++){
  298. if(st[j+9]==ATTACKED){
  299. int p=0;
  300. if(j>=2&&st[j-2]==HASKNIGHT&&st[j-1]!=HASKNIGHT)
  301. p=1;
  302. if(j<7&&st[j+2]==HASKNIGHT&&st[j+1]!=HASKNIGHT)
  303. p=1;
  304. if(p==0)break;
  305. }
  306. }
  307. if(j==9){
  308. bs[0][i]=c2;
  309. }
  310. }
  311. }
  312. #endif
  313. void putst()
  314. {
  315. #ifdef ENUM_ALL
  316. long long x=0;
  317. int i;
  318. for(i=0;i<18;i++){
  319. x|=((long long)st[i])<<(2*i);
  320. }
  321. sl[tc++]=x;
  322. #else
  323. tc++;
  324. #endif
  325. }
  326. int next9f()
  327. {
  328. int i;
  329. for(i=0;i<9;i++){
  330. if(st[i]==2){
  331. st[i]=0;
  332. }else{
  333. break;
  334. }
  335. }
  336. if(i==9)return 0;
  337. st[i]++;
  338. return 1;
  339. }
  340. int passe()
  341. {
  342. int i;
  343. for(i=0;i<9;i++){
  344. if(st[i]==NOTATTACKED){
  345. int p=1;
  346. if(i>=2&&st[9+i-2]==HASKNIGHT&&st[9+i-1]!=HASKNIGHT)p=0;
  347. if(i<7&&st[9+i+2]==HASKNIGHT&&st[9+i+1]!=HASKNIGHT)p=0;
  348. if(p==0)return 0;
  349. }
  350. }
  351. for(i=0;i<9;i++){
  352. if(st[9+i]==NOTATTACKED){
  353. int p=1;
  354. if(i>=2&&st[i-2]==HASKNIGHT&&st[i-1]!=HASKNIGHT)p=0;
  355. if(i<7&&st[i+2]==HASKNIGHT&&st[i+1]!=HASKNIGHT)p=0;
  356. if(p==0)return 0;
  357. }
  358. }
  359. return 1;
  360. }
  361. int next18()
  362. {
  363. int i;
  364. for(i=0;i<9;i++){
  365. if(st[i+9]==2){
  366. if(init[i]==NOTATTACKED){
  367. st[i+9]=0;
  368. }else{
  369. st[i+9]=1;
  370. }
  371. continue;
  372. }else if(st[i+9]==1){
  373. st[i+9]=2;
  374. return 1;
  375. }else{
  376. st[i+9]=1;
  377. return 1;
  378. }
  379. }
  380. return 0;
  381. }
  382. int first18()
  383. {
  384. int i;
  385. for(i=0;i<9;i++){
  386. switch(init[i]){
  387. case NOTATTACKED:
  388. st[i+9]=NOTATTACKED;
  389. break;
  390. case ATTACKED:
  391. st[i+9]=ATTACKED;
  392. break;
  393. default:
  394. fprintf(stderr,"invalid\n");
  395. exit(-1);
  396. }
  397. }
  398. return 1;
  399. }
  400. void ana18()
  401. {
  402. int i;
  403. for(i=0;i<9;i++)init[i]=0;
  404. for(i=0;i<9;i++){
  405. if(st[i]==HASKNIGHT){
  406. if(i>=2&&st[i-1]!=HASKNIGHT){
  407. init[i-2]=ATTACKED;
  408. }
  409. if(i<7&&st[i+1]!=HASKNIGHT)init[i+2]=ATTACKED;
  410. }
  411. }
  412. if(!first18())
  413. return;
  414. do{
  415. if(passe()){
  416. putst();
  417. }
  418. }while(next18());
  419. }
  420. void checkboard()
  421. {
  422. char status[10][9];
  423. char line[80];
  424. int i,j;
  425. for(i=0;i<10;i++){
  426. gets(line);
  427. int c=0;
  428. char *p=line;
  429. do{
  430. while(isspace(*p))p++;
  431. if(*p=='\0'){
  432. fprintf(stderr,"invalid input\n");
  433. exit(-1);
  434. }
  435. if(*p=='*')
  436. status[i][c++]=NOTATTACKED;
  437. else
  438. status[i][c++]=HASKNIGHT;
  439. p++;
  440. }while(c<9);
  441. }
  442. long long x;
  443. int c=0;
  444. for(i=0;i<9;i++)if(status[0][i]==HASKNIGHT)c++;
  445. for(i=0;i<9;i++){///line i and line i+1
  446. x=0ll;
  447. for(j=0;j<9;j++){
  448. if(status[i+1][j]==HASKNIGHT){
  449. if(j>=2&&status[i+1][j-1]!=HASKNIGHT&&status[i][j-2]==NOTATTACKED){
  450. status[i][j-2]=ATTACKED;
  451. }
  452. if(j<7&&status[i+1][j+1]!=HASKNIGHT&&status[i][j+2]==NOTATTACKED){
  453. status[i][j+2]=ATTACKED;
  454. }
  455. }
  456. if(status[i][j]==HASKNIGHT){
  457. if(j>=2&&status[i][j-1]!=HASKNIGHT&&status[i+1][j-2]==NOTATTACKED){
  458. status[i+1][j-2]=ATTACKED;
  459. }
  460. if(j<7&&status[i][j+1]!=HASKNIGHT&&status[i+1][j+2]==NOTATTACKED){
  461. status[i+1][j+2]=ATTACKED;
  462. }
  463. }
  464. if(i>0&&status[i-1][j]==HASKNIGHT){
  465. if(j>=1&&status[i][j]!=HASKNIGHT&&status[i+1][j-1]==NOTATTACKED){
  466. status[i+1][j-1]=ATTACKED;
  467. }
  468. if(j<8&&status[i][j]!=HASKNIGHT&&status[i+1][j+1]==NOTATTACKED){
  469. status[i+1][j+1]=ATTACKED;
  470. }
  471. }
  472. }
  473. if(i>0){//check line i-1, everything is attacked
  474. for(j=0;j<9;j++){
  475. if(status[i-1][j]==NOTATTACKED){
  476. int p=0;
  477. if(j>=1&&status[i+1][j-1]==HASKNIGHT&&status[i][j-1]!=HASKNIGHT){
  478. p=1;
  479. }
  480. if(j<8&&status[i+1][j+1]==HASKNIGHT&&status[i][j+1]!=HASKNIGHT){
  481. p=1;
  482. }
  483. if(p==0){
  484. fprintf(stderr,"invalid input, location %d,%d not attacked\n",i-1,j);
  485. exit(-1);
  486. }
  487. }
  488. }
  489. }
  490. for(j=0;j<9;j++){
  491. if(status[i+1][j]==HASKNIGHT)c++;
  492. x|=((long long)status[i][j])<<(2*j);
  493. x|=((long long)status[i+1][j])<<(2*j+18);
  494. }
  495. long long *p=lower_bound(sl,sl+NS,x);
  496. if(p==NULL||p>=sl+NS){
  497. fprintf(stderr,"status %llx in line %d~%d not found\n",x,i,i+1);
  498. exit(-1);
  499. }
  500. int index=p-sl;
  501. if(bs[i][index]==0||bs[i][index]>c){
  502. fprintf(stderr,"status %llx(index %d) in line %d~%d only use %d knights while limit is %d\n",x,index,i,i+1,c,bs[i][index]);
  503. nextline(i);
  504. exit(-1);
  505. }
  506. printf("status %llx(index %d) in line %d~%d use %d knights and limit is %d\n",x,index,i,i+1,c,bs[i][index]);
  507. }
  508. printf("success\n");
  509. }
  510. int _tmain(int argc, _TCHAR* argv[])
  511. {
  512. int i;
  513. #if 0
  514. do{
  515. ana18();
  516. }while(next9f());
  517. printf("total %d states\n",tc);
  518. if(tc!=NS){
  519. fprintf(stderr,"invalid count\n");
  520. return -1;
  521. }
  522. sort(sl,sl+NS);
  523. FILE *f=fopen("stats.dat","wb");
  524. fwrite(sl,sizeof(sl[0]),NS,f);
  525. fclose(f);
  526. tc=NS;
  527. #else
  528. FILE *f=fopen("stats.dat","rb");
  529. fread(sl,sizeof(sl[0]),NS,f);
  530. fclose(f);
  531. tc=NS;
  532. #endif
  533. #ifdef ENUM_ALL
  534. #ifdef DUMP_DATA
  535. init2();
  536. for(i=0;i<8;i++){
  537. nextline(i+1);
  538. }
  539. FILE *q=fopen("data.dat","wb");
  540. fwrite(bs,sizeof(bs[0][0]),9*NS,q);
  541. #else
  542. FILE *q=fopen("data.dat","rb");
  543. fread(bs,sizeof(bs[0][0]),9*NS,q);
  544. #endif
  545. fclose(q);
  546. // checkboard();
  547. findbestlast();
  548. // countall();
  549. #endif
  550. return 0;
  551. }
复制代码
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2013-7-6 08:53:15 | 显示全部楼层
楼主的帖子好多
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
您需要登录后才可以回帖 登录 | 欢迎注册

本版积分规则

小黑屋|手机版|数学研发网 ( 苏ICP备07505100号 )

GMT+8, 2024-11-21 20:51 , Processed in 0.026633 second(s), 16 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表