zoukankan      html  css  js  c++  java
  • SRM 511 DIV1 500pt(DP)

    题目简述

    给定n个数,两个人轮流取数,和之前两个人的取的数或起来,谁不能取数或者谁取到的数和之前的数或值为511谁输,问谁能够赢?

    题解

    刚开始的想法是直接搜,不过需要记录取过的值的状态,2^50显然超时。。。对于当前或值cur,或上一个数num,只有两种情况,要么是 cur|num==cur,

    对于这种数,只是把这个状态直接给下一个玩家,起到延缓一步的作用,他们的选取顺序对局面没有影响,可以先全部轮流取掉,如果这种数的个数大于当前已经取的数的数量,那么我们还可以选择这种数,如果选择这个数可以导致下一个局面必败,那么当前这个局面可以必赢。第二种情况就是cur|num!=cur,num肯定是没有取过的,如果存在一个数num导致下一个局面必败,那么当前这个局面也是必胜的。如果下一个局面必胜,那么当前局面就是必输的,我们可以用记忆化搜索实现上述过程~~~

    代码:

     1 vector<int>card;
     2 int dp[55][555], n;
     3 int dfs(int th, int mask)
     4 {
     5     if (mask == 511) return 1;
     6     if (th == n) return 0;
     7     if (~dp[th][mask]) return dp[th][mask];
     8     int cnt = 0;
     9     for (int i = 0; i < n; i++) if ((card[i] | mask ) == mask) cnt++;
    10     if (cnt > th && !dfs(th + 1, mask)) return dp[th][mask] = 1;
    11     for (int i = 0; i < n; i++) if ((card[i] | mask ) != mask)
    12         {
    13             if (!dfs(th + 1, mask | card[i])) return dp[th][mask] = 1;
    14         }
    15     return 0;
    16 }
    17 class FiveHundredEleven
    18 {
    19 public:
    20     string theWinner(vector <int> cards)
    21     {
    22         card = cards;
    23         n = card.size();
    24         memset(dp, -1, sizeof(dp));
    25         return dfs(0, 0) ? "Fox Ciel" : "Toastman";
    26     }
    27 };
  • 相关阅读:
    题解报告:hdu1995汉诺塔V(递推dp)
    黑色CSS3立体动画菜单
    jQuery计算器插件
    CSS3动画库animate.css
    缩略图悬浮效果的jQuery焦点图
    CSS伪元素实现的3D按钮
    CSS3 3D旋转按钮对话框
    jQuery仿Android锁屏图案应用
    jQuery横向图片手风琴
    jQuery滑动杆打分插件
  • 原文地址:https://www.cnblogs.com/zjbztianya/p/4159880.html
Copyright © 2011-2022 走看看