leetcode——464. 我能赢吗

  参考https://www.cnblogs.com/grandyang/p/6103525.html

  思路是遍历每一种可能性,得出必胜的走法。然而,用递归会存在很多的重复计算,所以可用动态规划存储下计算的状态,用map<int,bool>存储,其中int对应current,考虑,所以可以用int来存储1~20的数字是否使用,比如1,就相当于1|current 即将第一位 置1 ,以此类推。

  首先判断,如果maxChoosableInteger >= desiredTotal ,则先手必胜

  如果全部的和 小于 desiredTotal 则都是输的

  剩余情况采用循环遍历,然后将对应状态存储下来,若能赢,则返回 true

// Study.cpp: 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>
#include <vector>
#include <unordered_map>
#include <unordered_set>
#include <queue>
#include <string>
#include <algorithm>
#include <sstream>
#include <set>
#include <stack>
#define INT_MAX       2147483647    // maximum (signed) int value
#define INT_MIN     (-2147483647 - 1) // minimum (signed) int value
;
#define Min(x,y) (x)<(y)?(x):(y)

using namespace std;

int Max(int a, int b)
{
    return a > b ? a : b;
}

bool Helper(int length, int total, int used, unordered_map<int, bool> &map)
{
    if (map.count(used))
        return map[used];

    for (int i = 0; i < length; i++)
    {
        int current = (1 << i);
        //判断当前数字是否已经存在路径里面
        if ((current & used) == 0)
        {
            if (total <= i + 1 || !Helper(length, total - (i+1), used | current, map))
            {
                map[used] = true;
                return true;
            }
        }
    }
    map[used] = false;
    return false;
}
bool canIWin(int maxChoosableInteger, int desiredTotal) {
    //首先判断,如果maxChoosableInteger >= desiredTotal ,则先手必胜
    if (maxChoosableInteger >= desiredTotal)
        return true;
    //如果全部的和 小于 desiredTotal 则都是输的
    else if (maxChoosableInteger*(maxChoosableInteger + 1) >> 1 < desiredTotal)
        return false;

    unordered_map<int,bool> map;
    return Helper(maxChoosableInteger, desiredTotal, 0, map);
}

int main()
{
    int a, b;
    cin >> a >> b;
    cout << canIWin(a, b);

    system("pause");
    return 0;
}

 

posted @ 2018-08-03 11:16  何许  阅读(338)  评论(0编辑  收藏  举报