CF200C Football Championship

题面

题面翻译

这个题目是说,Berland 的国家队成功加入一场足球联赛的半决赛。下面是球赛的规则:

· 两队比赛,比赛结束后哪支队伍进的球比对方队伍多,哪方获胜。

· 胜利得3分,平局两队各得1分,失败不得分(得0分)。

· 这四队中得到第一或第二的队伍进入下一轮。

每个队伍的名次是由总得分来算的:分越多,名次越高。如果两个队伍有同样的分,以下列方式来决定高低(越靠前的规则越优先考虑,如果还是不能分出高低,再往下判断。下列第一个权重最高):

· 每个队的进球数减去失球数,得到的结果越高排名就越高。

· 总进球数越高,排名就越高。

· 如果以上都不行的话,则以字典序排列。

现在还有一场比赛未打。一共6场比赛,已知前五场的队伍与得分。某个队伍和Berland还没交战。教练想让你找到如此X:Y(X是Berland的得分,Y是另一只球队的得分),可以满足下列条件:

· X>Y,Berland得赢;

· Berland赢后,得进前二名;

· 如果不止一种答案,尽可能让X-Y小;

· 如果还是有很多答案(不止一个),你应该让Y尽可能小。

输入格式:

一共有五行。

每一行都是以“team1 team2 goals1:goals2”(没引号)形式出现。表示team1跟team2交战一局。team1进了goal1个球,team2进了goal2个球。team1和team2都是非空字符串,并且都是大写字母,总长度不超过20。goal1和goal2都是0~9的正整数。

Berland队名字是"BERLAND"。保证只有Berland和另一支队伍打了2场比赛,其他队打了3场。

输出格式:

输出比分X:Y。X是Berland分数,Y是另一只球队的分数。如果怎么样也无法得到第一或第二,输出一行"IMPOSSIBLE"(没引号)。

提示:最后一场分数也不一定小,比如10:0这种情况。

先说几句

很好的枚举法、STL 练习题。再说几句,感觉题目有点像,就是让 Berland 队和另一个队踢假球,使得 Berland 队成功晋级。但是,这场假球要做得尽可能真。带着这样的理解会更容易理解题意。

解题思路

在已知的场次中,把每个队伍的各种得分统计好。使用结构体更好地存储得分信息。如下。

struct node
{
	string name;	// 名称
	int score;		// 得分
	int jsq;		// 净胜球
	int zsq;		// 总进球数
	node()			// 初始化
	{
		score=jsq=zsq=0;
	}
};

有结构体,就一定有比较函数。按照题目描述写,不是很难。

bool cmp(node a, node b)
{
	if(a.score!=b.score)		// 1.得分
		return a.score>b.score;
	if(a.jsq!=b.jsq)			// 2.净胜球
		return a.jsq>b.jsq;
	if(a.zsq!=b.zsq)			// 3.总进球数
		return a.zsq>b.zsq;
	return a.name<b.name;		// 4.队名字典序
}

接下来进入主函数。输入时,用 map 嵌套 struct 记录每个队伍的详细信息。先使用 c n t cnt cnt 统计比赛次数,就可以知道 Berland 的对手是谁。

然后,枚举对手得分 y y y 和净胜球数 d d d,则 Berland 得分 x = y + d x=y+d x=y+d。拷贝一个新 map,改变双方得分信息,提取出 vector,排序,检查 Berland 的排名。如果循环完了没有解,输出 IMPOSSIBLE

y y y d d d 的枚举范围在 100 100 100 以内即可。

奉上代码

// 200C Football Championship
#include <bits/stdc++.h>
#define var long long
#define SIZE 200010
#define debug(x) cout<<#x<<":"<<x<<endl;
using namespace std;

struct node
{
	string name;
	int score;
	int jsq;
	int zsq;
	node()
	{
		score=jsq=zsq=0;
	}
};

bool cmp(node a, node b)
{
	if(a.score!=b.score)
		return a.score>b.score;
	if(a.jsq!=b.jsq)
		return a.jsq>b.jsq;
	if(a.zsq!=b.zsq)
		return a.zsq>b.zsq;
	return a.name<b.name;
}

int main()
{
	map<string, node> m;
	map<string, int> cnt;
	for(int i=0; i<5; i++)
	{
		string s1, s2; cin>>s1>>s2;
		cnt[s1]++; cnt[s2]++;
		m[s1].name=s1;
		m[s2].name=s2;
		int x, y;
		scanf("%d:%d", &x, &y);
		m[s1].zsq+=x;
		m[s2].zsq+=y;
		m[s1].jsq+=x-y;
		m[s2].jsq+=y-x;
		if(x>y)
			m[s1].score+=3;
		if(y>x)
			m[s2].score+=3;
		if(x==y)
		{
			m[s1].score++;
			m[s2].score++;
		}
	}
	string another;
	for(auto x:cnt)
		if(x.first!="BERLAND" && x.second==2)
		{
			another=x.first;
			break;
		}		
	/*
	for(auto x:m)	
	{
		cout<<x.second.name<<endl
			<<x.second.score<<endl
			<<x.second.jsq<<endl
			<<x.second.zsq<<endl
			<<endl;
	}
	*/
	for(int d=1; d<=100; d++)
		for(int y=0; y<=100; y++)	
		{
			//debug(d);
			int x=y+d;
			auto nm=m;
			nm["BERLAND"].score+=3;
			nm["BERLAND"].jsq+=d;
			nm[another].jsq+=-d;
			nm["BERLAND"].zsq+=x;
			nm[another].zsq+=y;
			vector<node> v;
			for(auto t:nm)
				v.push_back(t.second);
			sort(v.begin(), v.end(), cmp);
			if(v[0].name=="BERLAND" || v[1].name=="BERLAND")
			{
				cout<<x<<':'<<y;
				return 0;
			}
		}
	puts("IMPOSSIBLE");

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值