SRM 511 DIV 2

FiveHundredEleven

Posted by Nivin Anton Alexis Lawrence on January 22, 2018

Recently by the same author:


Introduction to Functional Programming [Part 2]

Think Functional


Nivin Anton Alexis Lawrence

Human

You may find interesting:


BIT + DP

Sum Over Subsets using Dynamic Programming


SRM 508 DIV 2

YetAnotherORProblem2

Problem Statement

Fox Ciel and Toastman are playing a game. The game uses a memory and N cards. Initially the value of the memory is set to zero. You are given a int[] cards containing exactly N elements. cards[i] is the number written on the i-th card. Ciel and Toastman take alternate turns, and Ciel plays first. In each turn, the player chooses a card and removes the card from the game (this card can’t be used later). If the chosen card contains x and the value of the memory is y, the value of the memory is changed to (x | y). The ‘|’ symbol stands for bitwise OR (see notes for clarification). If a player can’t make a move (because there are no cards left), or if after a player’s move the memory becomes 511, this player loses. Determine the winner when both players play optimally. If Fox Ciel wins, return “Fox Ciel”.

Tutorial

The problem is a variation of game theory problem. In this, both players play optimally. Consider a case where the number of N <= 10, then we can backtrack all possible permutation and output the result. But, we know that it doesn’t work for our constraints. In that case, we need to come with states and avoid recomputation. By understanding the game better, we can conclude that for any given round the memory score is what matters. Let us consider, player1, he can start the round with N possibilities. But, he picks the one that yields a winning. For any given Ith round with score M, the permutation of selection in the previous round doesn’t matter, and this works because of ‘|’ operation. Finally, the dp states will be [Score][Round]

Code

import java.util.*;
import java.math.*;
import static java.lang.Math.*;

public class FiveHundredEleven {


	int [][] dp = new int[560][55];
	int N;
	int [] cards;
	boolean [] visited = new boolean[55];
	int go(int memory_value, int n)
	{
		if(memory_value == 511)
			return (n % 2 == 0)? 1 : 0 ;
		if(n == N)
			return (n%2 == 0)? 0 : 1;

		int res = dp[memory_value][n];
		if(res != -1)
			return res;

		dp[memory_value][n] = (n % 2 == 0) ? 0 : 1;
		for(int i= 0 ; i < N ; i ++)
		{
			if(visited[i] == false)
			{
				visited[i] = true;
				if(n%2 == 0)
					dp[memory_value][n] = max(dp[memory_value][n], go(memory_value | cards[i], n+1));
				else
					dp[memory_value][n] = min(dp[memory_value][n], go(memory_value | cards[i], n+1));
				visited[i] = false;
			}

		}
		return dp[memory_value][n];
	}


	public String theWinner(int[] cards) {

		for(int i = 0 ; i < 560 ; i ++)
			Arrays.fill(dp[i], -1);
		N = cards.length;

		this.cards = cards;
		int aux = go(0, 0);

		if(aux == 0)
			return "Toastman";
		return "Fox Ciel";
	}
}