• UVA 10404 Bachet's Game(dp + 博弈?)


    Problem B: Bachet's Game

    Bachet's game is probably known to all but probably not by this name. Initially there are  n  stones on the table. There are two players Stan and Ollie, who move alternately. Stan always starts. The legal moves consist in removing at least one but not more than  k  stones from the table. The winner is the one to take the last stone.

    Here we consider a variation of this game. The number of stones that can be removed in a single move must be a member of a certain set of m numbers. Among the m numbers there is always 1 and thus the game never stalls.

    Input

    The input consists of a number of lines. Each line describes one game by a sequence of positive numbers. The first number is  n  <= 1000000 the number of stones on the table; the second number is  m  <= 10 giving the number of numbers that follow; the last  m  numbers on the line specify how many stones can be removed from the table in a single move.

    Input

    For each line of input, output one line saying either  Stan wins  or  Ollie wins  assuming that both of them play perfectly.

    Sample input

    20 3 1 3 8
    21 3 1 3 8
    22 3 1 3 8
    23 3 1 3 8
    1000000 10 1 23 38 11 7 5 4 8 3 13
    999996 10 1 23 38 11 7 5 4 8 3 13
    

    Output for sample input

    Stan wins
    Stan wins
    Ollie wins
    Stan wins
    Stan wins
    Ollie wins

    题意:给定n个石头,和m种去除石头的方式,每种方式可以去除一定量的石头, 现在Stan(简称S),Ollie(简称O),S先手,O后手,每次每个人能选择一种去除石头的方式,谁去除最后一堆谁就赢了。要求出必胜之人是谁。

    思路:一开始没头绪,以为是博弈。没想出好的思路。由于n很大,去遍历状态肯定超时。之后看了别人的题解,才发现不错的dp思路:用一个dp数组记录,对于先手者能取到的记录为1,后手者为0,初始都为0,遍历1到n,如果dp[i]为0,说明上一手是后手取得,这样先手就能取,把dp[i]变为1,由于是从1 到 n,这样每个状态记录时,前面的都已经记录好了,所以是可行的。这样最后只需要判断dp[n]是1,还是0,就可以判断是先手胜还是后手胜了。

    状态转移方程为:if (i - move[j] >= 0 && !dp[i - move[j]])  dp[i] = 1。

    代码:

    #include <stdio.h>
    #include <string.h>
    
    int n, m, move[15], dp[1000005], i, j;
    
    int main() {
    	while (~scanf("%d", &n)) {
    		memset(dp, 0, sizeof(dp));
    		scanf("%d", &m);
    		for (i = 0; i < m; i ++) {
    			scanf("%d", &move[i]);
    		}
    		for (i = 1; i <= n; i ++)
    			for (j = 0; j < m; j ++) {
    				if (i - move[j] >= 0 && !dp[i - move[j]]) {
    					dp[i] = 1;
    					break;
    				}
    			}
    		if (dp[n])
    			printf("Stan wins
    ");
    		else
    			printf("Ollie wins
    ");
    	}
    	return 0;
    }


  • 相关阅读:
    [转]Angular4首页加载慢优化之路
    [转]angular 禁止缓存
    微服务之分布式跟踪系统(springboot+pinpoint)
    分布式追踪系统设计与实现
    QLExpress 规则引擎使用介绍
    几个常见规则引擎的简单介绍和演示
    大数据对账
    美团配送资金安全治理之对账体系建设
    美的支付-对账系统实现
    redis实现对账(集合比较)功能
  • 原文地址:https://www.cnblogs.com/riskyer/p/3296999.html
Copyright © 2020-2023  润新知