ACM/ICPC2012年全国邀请赛金华赛区 F题 chess(博弈搜索)

59 篇文章 0 订阅
17 篇文章 0 订阅
这篇博客详细介绍了2012年ACM/ICPC全国邀请赛金华赛区的F题——Chess,涉及到博弈搜索的策略和解决方案。博主分享了题目的具体要求,以及如何通过编程来解决这个棋盘游戏问题,提供了提交代码的链接,供读者参考和实践。
摘要由CSDN通过智能技术生成

题目:点这里~~ 

提交:点这里~~

AC_CODE

#define boy 0
#define girl 1
const int Max_N = 5 ;
char table[Max_N][Max_N]  ;
vector< pair<int ,int> > can ;//可以放棋子
string result ;//expectation
bool used[Max_N][Max_N] ;//used[i][j]棋格是否已经被使用
char boychess , grilchess;//每个case,男生,女生走的棋子

int Win(char ch){//判断棋子是不是已经形成连4
    int i , j , n ;
    for(i = 1 ; i <= 4 ; i++){
         n = 0 ;
         for(j = 1 ; j <= 4 ; j++)
            n += table[i][j] == ch ;
         if(n == 4)
            return 1 ;
    }
    for(i = 1 ; i <= 4 ; i++){
         n = 0 ;
         for(j = 1 ; j <= 4 ; j++)
            n += table[j][i] == ch ;
         if(n == 4)
            return 1 ;
    }
    n = 0 ;
    for(i = 1 ; i <= 4 ; i++)
        n += table[i][i] == ch ;
    if(n == 4)
        return 1 ;
    n = 0 ;
    for(i = 1 ; i <= 4 ; i++)
        n += table[i][5-i] == ch ;
    if(n == 4)
        return 1 ;
    return 0 ;
}


int  dfs(int who){
    
     if(who == boy){
           if(Win(grilchess))//本轮是男生,判断上一轮女生放完之后的结果
              return result == "LOSE"   ;//如果上轮女生已赢,判断expectation是不是LOSE
     }
     else{
           if(Win(boychess))//本轮是女生,判断上一轮男生放完之后的结果
               return result == "WIN" ;//如果上轮男生已赢,判断expectation是不是WIN
     }
     int sum = 0  , statisfy  = 0 ;
     for(int i = 0 ; i < can.size() ; i++){
          int x = can[i].first ;
          int y = can[i].second ;
          if(! used[x][y]){
                sum++ ; //本轮总共可放棋子的数量
                used[x][y] = 1 ;//标记已用
                if(who == boy)
                    table[x][y] = boychess ;
                else
                    table[x][y] = grilchess ;
                if(dfs(!who))//递归判断下轮情况,如果满足expectation,则次数加1
                   statisfy++ ;
                used[x][y] = 0 ;
                table[x][y] = '.' ;
                if(who == boy && statisfy > 0)//本轮男生走棋,在本轮的多次可能中,只要能满足expectation一次就行
                     return 1 ;
                if(who == girl && statisfy < sum)//本轮女生走棋,在本轮的多次可能中,只有全部满足expectation才行
                     return 0 ;
          }
     }
     if(sum == 0)//已经没有地方可放,则平局
        return result == "TIE" ;//判断expectation是不是“TIE”
     if(who == boy)
        return statisfy > 0 ;//本轮男生走棋,在本轮的多次可能中,只要能满足expectation一次就行
     else
        return statisfy == sum ;//本轮女生走棋,在本轮的多次可能中,只有全部满足expectation才行
}


int main(){
    int T , i , j , n_x , n_o ;
    cin>>T ;
    while(T--){
          cin>>result ;
          for(i = 1 ; i <= 4 ; i++)
              scanf("%s" , table[i]+1) ;
          can.clear() ;
          n_x = n_o = 0 ;
          for(i = 1 ; i <= 4 ; i++){
             for(j = 1 ; j <= 4 ; j++){
                  if(table[i][j] == '.'){
                      can.push_back(make_pair(i , j)) ;
                      used[i][j] = 0  ;//可以使用标为0
                  }
                  else{
                      used[i][j] = 1  ;
                      if(table[i][j] == 'x')//分别统计棋子x和o的个数
                           n_x++ ;
                      else
                           n_o++ ;
                  }
             }
          }
          if(n_x == n_o){//如果x与o的个数一样多,则XXX该放x
               boychess = 'x' ;
               grilchess = 'o';
          }
          else{//如果x比o多一个,则XXX该放o
               boychess = 'o';
               grilchess = 'x';
          }
          if(dfs(boy))
               puts("YES") ;
          else
               puts("NO") ;
    }
    return 0 ;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值