花生米三连发(动规)

1.时限:1000ms 内存限制:10000K  总时限:3000ms

描述
五一长假第二天,Tom和Jerry在仓库散步的时候又发现了一堆花生米(这个仓库还真奇怪)。这次Tom制定分花生米规则如下:
       1、Tom和Jerry轮流从堆中取出k粒花生米吃掉,k可以是1,5,10中的任意一个数字;
       2、为显示规则的公平性,Jerry可以选择先取或者后取。
Jerry当然还是希望最后一粒花生米被Tom吃掉。请计算,Jerry为了达到目的应该先取还是后取。
 
输入
本题有多个测例,每个测例的输入是一个整数n,n大于零小于等于1000,代表花生米的数量。
n等于0表示输入结束,不需要处理。
 
输出
每个测例在单独的一行内输出一个整数:Jerry先取输出1;Tom先取输出0。
 
输入样例
1
2
3
4
0
 
输出样例
0
1
0
1
 
提示
 
来源

2.时限:1000ms 内存限制:10000K  总时限:3000ms

描述
五一长假第三天,Tom和Jerry在仓库散步的时候又发现了一堆花生米(仓库,又见仓库……)。这次Tom制定分花生米规则如下:
???????1、Tom和Jerry轮流从堆中取出k粒花生米吃掉;
2、第一次取花生米的人只能取一粒,以后取花生米的数量不能超过前一个人取花生米数量的两倍;
3、为显示规则的公平性,Jerry可以选择先取或者后取。
Jerry当然还是希望最后一粒花生米被Tom吃掉。请计算,Jerry为了达到目的应该先取还是后取。
 
输入
本题有多个测例,每个测例的输入是一个整数n,n大于零小于等于1000,代表花生米的数量。
n等于0表示输入结束,不需要处理。
 
输出
每个测例在单独的一行内输出一个整数:Jerry先取输出1;Tom先取输出0。
 
输入样例
1
2
3
4
5
0
 
输出样例
0
1
0
0
1
 
提示
 
来源

3.时限:1000ms 内存限制:10000K  总时限:3000ms

描述
五一长假第六天,Tom在QQ上遇到了Kitty。呵呵,Kitty,在离散数学课上认识的PPMM……等等!Tom恍然大悟:自己这一生除了看帖不回之外最大的错误就是离散数学没学好!
五一长假第七天,Tom和Jerry在仓库散步的时候发现了一堆花生米(仓库,呵呵,仓库…)。这次Tom制定分花生米规则如下:
???????1、首先选出最苦的一粒花生米,放到一个瓶子里;
???????2、把剩下的花生米做成花生酱,Tom和Jerry轮流取一些花生酱吃掉;
???????3、第一个取的人只能取1.0克,以后取花生酱的数量不能少于两个人已经取过的总数量且不能超过两个人已经取过的总数量的三倍;
?????? 4、不能按规则3取花生酱的人必须吃掉瓶子里的花生米;
?????? 5、为显示规则的公平性,Jerry可以选择先取或者后取。
Jerry当然希望瓶子里的花生米被Tom吃掉。请计算,Jerry为了达到目的应该先取还是后取。
 
输入
本题有多个测例,每个测例的输入是一个浮点数w,w大于1.0小于等于1000.0,w最多只有一位小数,代表花生酱的数量,单位为克。
w小于0表示输入结束,不需要处理。
 
输出
每个测例在单独的一行内输出一个整数:Jerry先取输出1;Tom先取输出0。
 
输入样例
1.5
7.9
-1
 
输出样例
1
0
 
提示
 
来源
 

三道题都是相似的动态规划,在考虑第i步的策略的时候要考虑前几步的状态。
要注意的是,如果前几步全是JERRY赢,那么这一步让TOM来去,如果有TOM赢得可能,那就必须JERRY取,因为TOM是在乱取的,而JERRY是有策略的。

#include 
#include 

int main()//1
{
	int i, n;
	bool dp[1002];//tom是ture,jerry是false
	dp[1] = true;
	i = 2;
	for (i = 2; i <= 1000; i++)
	{
			if (i - 1 >= 1 && i - 5 < 1)
			{
				if (dp[i - 1] == false)
				{
					dp[i] = true;
				}
				else
				{
					dp[i] = false;
				}
			}
			else if (i - 5 >= 1 && i - 10 < 1)
			{
				if (dp[i - 1] == false && dp[i - 5] == false)
				{
					dp[i] = true;
				}
				else
				{
					dp[i] = false;
				}
			}
			else if (i - 10 >= 1)
			{
				if (dp[i - 1] == false && dp[i - 5] == false && dp[i - 10] == false)
				{
					dp[i] = true;
				}
				else
				{
					dp[i] = false;
				}
			}
	}
	while (1)
	{
		scanf("%d", &n);
		if (n == 0)
		{
			break;
		}
		else
		{
			if (dp[n] == true)
			{
				printf("0\n");
			}
			else
			{
				printf("1\n");
			}
		}
	}
	return 0;
}
#include 
#include 

using  namespace std;//2

bool dp[2002][2002];//tom为true,jerry为false

void figure(int a, int b)
{
	int i, flag;
	if (b == 1)
	{
		if (dp[a - 1][2] == false)
		{
			dp[a][1] = true;
		}
		else
		{
			dp[a][1] = false;
		}
	}
	else if (a == b + 1)//刚好位于对角线下一格的话依然jerry,因为dp[n][n-1]总能跳转到tom上
	{
		dp[a][b] = false;
	}
	else if (b>1)
	{
		flag = 0;
		for (i = 1; i <= b && 2 * i < a; i++)
		{
			if (dp[a - i][2 * i] == true)//状态转移到了tom上
			{
				flag = 1;
				dp[a][b] = false;
				break;
			}
		}
		if (flag == 0)//状态转移不到tom上
		{
			dp[a][b] = true;
		}
	}
	return;
}

int main()
{
	int i, j, n;
	for (i = 1; i <= 1001; i++)
	{
		dp[i][i] = false;//对角线全jerry
		dp[1][i] = true;
		dp[2][i] = false;
	}
	for (i = 3; i <= 1000; i++)
	{
		for (j = 1; j < i; j++)
		{
			figure(i, j);//探讨dp[i][j]的状态
		}
	}
	while (1)
	{
		scanf("%d", &n);
		if (n == 0)
		{
			break;
		}
		else
		{
			if (dp[n][1] == true)
			{
				printf("0\n");
			}
			else
			{
				printf("1\n");
			}
		}
	}
	return 0;
}
#include 
#include 
#include 

using namespace std;//3

char dp[10002];

int main()
{
	int i, n, die, k, flag, j;
	double x;
	while (1)
	{
		memset(dp, 0, sizeof(dp));
		scanf("%lf", &x);
		if (x < 0)
		{
			break;
		}
		n = (int)(x * 10);
		if (n <= 10)
		{
			printf("1\n");
			continue;
		}
		die = n / 2;
		for (i = 1; i <= die - 1 ; i++)
		{
			dp[i] = 'T';//低于花生酱数量一半的应该全都是tom
		}
		if (n % 2 == 1)
		{
			dp[i] = 'T';
		}
		else
		{
			dp[i] = 'J';
		}
		for (i = die + 1; i <= n - 10; i++)
		{
			k = n - i;//k表示已经吃掉的数量
			flag = 0;//先假设没找到T
			if (i <= 3 * k)
			{
				for (j = 1; j <= i - k; j++)
				{
					if (dp[j] == 'T')
					{
						flag = 1;//找到了T
						dp[i] = 'J';
						break;
					}
				}
			}
			else
			{
				for (j = i - 3 * k; j <= i - k ; j++)
				{
					if (dp[j] == 'T')
					{
						flag = 1;
						dp[i] = 'J';
						break;
					}
				}
			}
			if (flag == 0)
			{
				dp[i] = 'T';
			}
		}
		if (dp[n - 10] == 'T')
		{
			printf("1\n");
		}
		else if (dp[n - 10] == 'J')
		{
			printf("0\n");
		}
	}
	return 0;
}



你可能感兴趣的:(算法与ACM,动态规划)