POJ1323------Game Prediction

9 篇文章 0 订阅
2 篇文章 0 订阅

问题描述:

Game Prediction
Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 9680 Accepted: 4626
Description


Suppose there are M people, including you, playing a special card game. At the beginning, each player receives N cards. The pip of a card is a positive integer which is at most N*M. And there are no two cards with the same pip. During a round, each player chooses one card to compare with others. The player whose card with the biggest pip wins the round, and then the next round begins. After N rounds, when all the cards of each player have been chosen, the player who has won the most rounds is the winner of the game. 






Given your cards received at the beginning, write a program to tell the maximal number of rounds that you may at least win during the whole game. 
Input


The input consists of several test cases. The first line of each case contains two integers m (2?20) and n (1?50), representing the number of players and the number of cards each player receives at the beginning of the game, respectively. This followed by a line with n positive integers, representing the pips of cards you received at the beginning. Then a blank line follows to separate the cases. 


The input is terminated by a line with two zeros. 
Output


For each test case, output a line consisting of the test case number followed by the number of rounds you will at least win during the game. 


Sample Input


2 5
1 7 2 10 9


6 11
62 63 54 66 65 61 57 56 50 53 48


0 0
Sample Output


Case 1: 2

Case 2: 4


解法:

这道题目的原理特别简单,就一句话。因为要求A的最少赢的次数,而赢的条件是A所出的牌的数字是最大的,我们只要求出比A所有的牌大的拍的数量(不能重复,比如说,A有对于A的两张牌,2,3,对方有4,4比2大,也比3大,但由于一张牌只能算一次,所以只要从比A所有的最小的那张牌开始计算,并且吧重复的去掉就可以了)。(*)对这种假设做了处理

#include<iostream>
#include<fstream>
#include<cstdlib>
using namespace std;

ifstream fin("C:\\data41.in");

int m,n;
int pip[1001];

int search(int min)
{
	int cnt=0;
	for(int num=min+1,pos=min;num<=n*m&&pos<=n*m;++pos,++num)
	{
		while(pip[pos]!=1&&pos<=n*m)                 (*)
			++pos;
		while(!(num>pos&&pip[num]==0)&&num<=n*m)     (*)
		++num;
		++cnt;
	}
	return n-cnt+1;
}

int main()
{
	int p,cnt;
	cnt=0;
	int min=32797;
	while(fin>>m>>n&&m!=0&&n!=0)
	{
		memset(pip,0,sizeof(pip));
		for(int j=0;j<n;++j)
		{
			fin>>p;
			min<?=p;
			pip[p]=1;
		}
		cout<<"case "<<++cnt<<":"<<search(min)<<endl;
	}
	system("pause");
	return 0;
}


有了上面的解法,我有对这个算法做出了改进,可以直接算答案了。

这个改进后的算法和改进前的算法的原理是一样的,(**)中的三元运算对上面的假设做出处理。但由于上面的算法有一个标记数组,而这个改进后的算法没有标记数组,所以要先对A手中的牌进行排序,然后才可以用上面的原理来算。

#include<iostream>
#include<fstream>
#include<cstdlib>
using namespace std;

ifstream fin("C:\\data41.in");

int m,n;
int pip[50];

void sort()
{
	for(int i=1;i<n;++i)
	{
		int temp;
		for(int j=i;j>0;--j)
		{
			if(pip[j]<pip[j-1])
			{
				temp=pip[j];
				pip[j]=pip[j-1];
				pip[j-1]=temp;
			}
		}
	}
}

int DP()
{
	int cnt=0;
	for(int i=1;i<n;++i)
	{
		int sub=pip[i]-pip[i-1]-1;
		cnt=(cnt+sub<i)?(cnt+sub):i;           (**)
	}
	int sub=m*n-pip[n-1];
	cnt=(cnt+sub<n-1)?(cnt+sub):(n-1);             (**)
	return n-cnt;
}

int main()
{
	int cnt=0;
	while(fin>>m>>n&&m!=0&&n!=0)
	{
		for(int i=0;i<n;++i)
			fin>>pip[i];
		sort();
		int minmax=DP();
		cout<<"case "<<++cnt<<":"<<minmax<<endl;
	}
	system("pause");
	return 0;
}


这个改进后的算法既节约空间,有减少了运算量。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值