首页 | 编程语言 | 网站建设 | 游戏天堂 | 冲浪宝典 | 网络安全 | 操作系统 | 软件时空 | 硬件指南 | 病毒相关 | IT 认证
软讯网络 > 编程语言 > C/C++ > PKU1568 Find the Winning Move
【标  题】:PKU1568 Find the Winning Move
【关键字】:PKU1568,Find,the,Winning,Move
【来  源】:http://www.cppblog.com/sicheng/archive/2007/03/02/19134.html

PKU1568 Find the Winning Move

Find the Winning Move
Time Limit:3000MS? Memory Limit:32768K
Total Submit:120 Accepted:67

Description
4x4 tic-tac-toe is played on a board with four rows (numbered 0 to 3 from top to bottom) and four columns (numbered 0 to 3 from left to right). There are two players, x and o, who move alternately with x always going first. The game is won by the first player to get four of his or her pieces on the same row, column, or diagonal. If the board is full and neither player has won then the game is a draw.
Assuming that it is x's turn to move, x is said to have a forced win if x can make a move such that no matter what moves o makes for the rest of the game, x can win. This does not necessarily mean that x will win on the very next move, although that is a possibility. It means that x has a winning strategy that will guarantee an eventual victory regardless of what o does.

Your job is to write a program that, given a partially-completed game with x to move next, will determine whether x has a forced win. You can assume that each player has made at least two moves, that the game has not already been won by either player, and that the board is not full.

Input
The input contains one or more test cases, followed by a line beginning with a dollar sign that signals the end of the file. Each test case begins with a line containing a question mark and is followed by four lines representing the board; formatting is exactly as shown in the example. The characters used in a board description are the period (representing an empty space), lowercase x, and lowercase o. For each test case, output a line containing the (row, column) position of the first forced win for x, or '#####' if there is no forced win. Format the output exactly as shown in the example.

Output
For this problem, the first forced win is determined by board position, not the number of moves required for victory. Search for a forced win by examining positions (0, 0), (0, 1), (0, 2), (0, 3), (1, 0), (1, 1), ..., (3, 2), (3, 3), in that order, and output the first forced win you find. In the second test case below, note that x could win immediately by playing at (0, 3) or (2, 0), but playing at (0, 1) will still ensure victory (although it unnecessarily delays it), and position (0, 1) comes first.

Sample Input

?
....
.xo.
.ox.
....
?
o...
.ox.
.xxx
xooo
$

Sample Output

#####
(0,1)

Source
Mid-Central USA 1999

这个博弈 我用了Alpha-Beta剪枝 搜索是标准的极大极小的搜索过程
hash用的是4进制的便于位运算的hash
Solution
//by oyjpArt
#include <stdio.h>
#include <string.h>
char brd[4][4];
const int MAX = (1<<24)+1;
char hash[MAX];
char init[4][4];

bool win(char a) {
?//hor
?int i, j;
?for(i = 0; i<4; i++) {
??for(j = 0; j<4; j++)
???if(brd[i][j] != a)
????break;
??if(j == 4) return 1;
?}
?//ver
?for(i = 0; i<4; i++) {
??for(j = 0; j<4; j++)
???if(brd[j][i] != a)
????break;
??if(j == 4) return 1;
?}
?//dia
?if(brd[0][0] == a&& brd[1][1] == a && brd[2][2] == a && brd[3][3] == a) return 1;
?if(brd[0][3] == a&& brd[1][2] == a && brd[2][1] == a && brd[3][0] == a) return 1;
?return 0;
}

int res() {
?int i, j;
?if(win('x')) return 2;
?if(win('o')) return -2;
?for(i = 0; i<4; i++)
?? for(j = 0; j<4; j++)
??? if(brd[i][j] == '.')
???? return 1;
?return 0;
}

int hash_brd() { //4进制 便于2进制的hash
?int i, j, idx = 0, addr = 0;
?for(i = 0; i<4; i++)
??for(j = 0; j<4; j++)
???if(init[i][j] == '.') {
????if(brd[i][j] == 'o') ?addr |= 1<<(idx*2);
????else if(brd[i][j] == 'x')?addr |= 1<<(idx*2+1);
????idx++;
???}
?return addr;
}

int search(int player, int sta) {
?int hashbrd = hash_brd();
?if(hash[hashbrd] != -1) return hash[hashbrd];
?int i, j, tmp;
?int result = res();
?if(result != 1) {
??hash[hashbrd] = result;
??return result;
?}
?int min = 100, max = -100;
?if(player == 0) { //对方选min 如果子局面搜到了一个比当前min还大的 就不用搜了
??for(i = 0; i<4; i++) {
???for(j = 0; j<4; j++)
????if(brd[i][j] == '.') {
?????brd[i][j] = 'o';
?????if( (tmp = search(1, min)) < min ) min = tmp;
?????brd[i][j] = '.';
?????if(min == -2 || min <= sta) break;
????}
???if(j != 4) break;
??}
??hash[hashbrd] = min;
??return min;
?}
?else {
??for(i = 0; i<4; i++) {
???for(j = 0; j<4; j++)
????if(brd[i][j] == '.') {
?????brd[i][j] = 'x'; //如果子局面搜索时搜到比当前max小的 就不用搜了
?????if( (tmp = search(0, max)) > max) max = tmp;
?????brd[i][j] = '.';
?????if(max >= sta || max == 2) break;
????}
???if(j != 4) break;
??}
??hash[hashbrd] = max;
??return max;
?}
}

????
int main() {
//?freopen("t.in", "r", stdin);
?char tmp[2];
?int i, j;
?while(scanf("%s", tmp), strcmp(tmp, "$") != 0) {
??memset(hash, -1, sizeof(hash));
??for(i = 0; i<4; i++)
???scanf("%s", brd[i]);
??memcpy(init, brd, sizeof(brd));
??for(i = 0; i<4; i++) {
???for(j = 0; j<4; j++)
????if(brd[i][j] == '.') {
?????brd[i][j] = 'x';
?????if(search(0, -100) == 2) {
??????printf("(%d,%d)\n", i, j);
??????break;
?????}
?????brd[i][j] = '.';
????}
???if(j != 4) break;
??}
??if(i == 4) printf("#####\n");
?}
?return 0;
}

?

Tomcat 6 released and stable:【上一篇】
Control Spy 2.0:【下一篇】
【相关文章】
  • Oracle moves a step closer to Fusion
  • find命令
  • 《CSS设计禅机(the Zen of CSS Design)》译者序(草稿)
  • Mysql 大量 unauthenticated user
  • cnblog is cool and will post the 1st paper here
  • The Linux MTD, JFFS HOWTO - (第2部分) FAQ (未完待续 2007/2/27)
  • MsAjax Lib-> Array.remove 函数
  • MsAjax Lib-> Array.removeAt 函数
  • Item 34. Name Lookup and the Interface Principle part 4
  • STL中的remove问题
  • 【随机文章】
  • offsetof[转]
  • 动态语言和静态语言、强类型定义语言和弱类型定义语言的概念区分
  • 收集大梦的一篇DB2 联邦数据库配置的文章
  • 实战破解Windows Vista Beta 2的本地密码
  • 我得workstation
  • 用Socket类构建网页下载器
  • Linux 环境下的高级隐藏技术
  • SNMP+MRTG笔记
  • 各位大侠,帮帮忙吧,看看这个程序有什么问题啊,我运行的时候怎么会有错误啊!!
  • [VC++]WM_SYSCOMMAND
  • 【相关评论】
    没有相关评论
    【发表评论】
    姓名:
    邮件:
    随机码*
    评论*
          
    |  首 页  |  版权声明  |  联系我们   |  网站地图  |
    CopyRight © 2004-2007 软讯网络 All Rigths Reserved.