SOJ 1047

1047. Super Snooker

Constraints

Time Limit: 1 secs, Memory Limit: 32 MB

Description

On one of my many interplanetary travels I landed on a beautiful little planet called Crucible. It was inhabited by an extremely peace-loving people who called themselves Snooks. They received me very gracefully and told me I had arrived at precisely the right time, as the biggest event of the year was just then taking place: the Super Snooker Championship. Of course I couldn’t decline an invitation to go and watch. 
That year the Super Snooker Championship was contested by two experienced Snooks universally ac-claimed as the best players on the planet: Stephanie McHendry and Joanna McHiggins. The game involved an immense rectangular table covered with green cloth and lined by edges two inches high, except in the four corners and in the middle of the longer sides where there were holes. On it were put a number of balls (from 6 up to as many as 25), each representing a value or certain number of points (anywhere from 2 to 1000, but numbered consecutively). Each player in turn tried to nudge the lowest valued ball left on the table into one of the holes on the edges of the table using a strange limb called a “kew”. If one succeeded, she was said to have “podded” the ball and the value of the podded ball was added to her score. 
But here is the strange thing: the object of the game was not to finish with more points than the opponent. No, being a people who loved peace above all else, the object for both players was to end up with an equal number of points. This presented a bit of a problem. It was very important to them to know if it was possible to finish equal given the score of both players and the values of the balls left on the table. For instance, with a score-line of 56–34 and three balls left with values 13, 14 and 15, it is impossible to reach equal end-scores. If there are five balls left with values 20–24, it is possible: 56 + 20 + 24 = 34 + 21 + 22 + 23 = 100. You are asked to write a program that helps the Snooks by calculating whether it is possible for two Super Snooker players to win their game by finishing equal, given a score-line and the range of values of the range of the remaining balls. 

Input

The input consists of a line containing the number of configurations N (0 ≤ N ≤ 10000) to be calculated. It is followed by N lines each containing two scores and the lowest and highest values of the remaining balls.

Output

The output consists of one line for each configuration with the string ‘possible’ or the string ‘not possible’, depending on whether it is possible or not to finish equal from the given configuration.

Sample Input

5
56 34 13 15
56 34 20 24
0 0 500 519
0 0 500 520
0 0 500 521

Sample Output

not possible
possible
possible
not possible

not possible

这题肯定不能先进行分配然后再验证这种分配能否达到平局,因为这样最多要进行2^k尝试(假设还剩k个球),更高效的做法是先求出能达到平局的分配方法,然后再验证这种分配能否取到。验证是否能取到也不难,假设能达到平局的分配方法是给其中一方d分,然后先验证给这一方0个球他所能得到分数的上下限,若d在这区间中则可以取到,若不在则验证给这一方分1个球分数的上下限,依此类推直到k个球,若d始终不再任何区间内则说明d无法取到,即不可能达到平局。分j个球的下限即为取前j个球,上限是取后j个球。

#include<iostream>
#include<cmath>
#include<cstdlib>
using namespace std;
int N,flag; //N为case数,flag记录是否能平局,flag为1代表可能 
int score1,score2,Start,End;//score1,score2分别保存当前的比分,Start为剩余分数的起始,End为终止 
int getsum(int start,int end)//计算剩下球的总分数 
{
	return (start+end)*(end-start+1)/2;
}
int main()
{
	cin>>N;
	for(int i=0;i<N;++i)
	{
		flag=1;
		cin>>score1>>score2>>Start>>End;
		int	sum=getsum(Start,End);
		int minus=fabs(score1-score2);
		/*如果剩下球的总分数小于当前比分之差的话则必定不可能平局 。如果不小于的话通过计算可得较小的那方需要分得(sum+minus)/2的分数,较大的分得(sum-minus)/2的分数,所以若sum-minus不是偶数的话则较大的那方应分得的分数应为小数,而剩余球的分数全为整数,不可能出现所得分数为非整数的情况,所以不可能平局 */ 
		if(sum<minus||(sum-minus)%2!=0) flag=0;
		if(!flag) cout<<"not possible"<<endl;
		else
		{
			flag=0;
			int number=(sum-minus)/2;//number为较大的一方应分得的分数 
			int length=End-Start+1;//length为剩余球的总数 
			int MIN;
			int MAX;//MIN和MAX分别保存给当前分数较大的一方分配n个球时(n=0,1,2...length)他所能获得分数的上下限 ,如果number在任何一种情况的上下限之间时则代表至少有一种分配能达成平局 
			if(number==0) flag=1;//此为分配0个球的情况 
			for(int j=1;j<=length;++j)//分配n个球时的下线就是取前n个分数,上限就是取后n个分数 
			{
				MIN=MAX=0;
				for(int k=Start;k<Start+j;++k)
				    MIN+=k;
				for(int k=End;k>End-j;--k)
				   MAX+=k;
				if(number>=MIN&&number<=MAX)//由于上下限间的任意整数都是可以取到的,所有number在上限间说明number可以被取到,即代表可以达到平局 
				{
					flag=1;
					break;
				}
			}
			if(flag) cout<<"possible"<<endl;
		    else cout<<"not possible"<<endl;
		}
		
	}
}


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值