Codeforces Football Championship

地址:http://codeforces.com/contest/200/problem/C

模拟题

题意:模拟足球小组赛的排名变化。规定只有4个球队,我方球队为BERLAND,一定会有的,然后另外3个球队的名字不一定。4个球队,两两球队间打且仅打一场比赛(所以可以知道一共是打了6场)。输入中给出5行,即5场比赛的信息,还剩下一场的信息没有给出。保证最后一场一定是BERLAND打某个队的,对手是谁要找出来(这个不难),而且也规定这场比赛一定是BERLAND胜利。你的任务是,要令BERLAND在这场比赛后,排在第1名或第2名,满足这个条件下,这场比赛的净胜球数最少,如果净胜球数一样,要令对方的进球数最少。如果无论怎样都无法让BERLAND排在前2名,则输出IMPOSSIBLE

输出最后一场比赛的比分,例如sample中6:0,6是BERLAND的进球数

排名规则:

1.两队比赛,胜方得积分3,败方得积分0。平局两方各得积分1

2.按积分排名,高积分排前面

3.如果积分相同,按6场比赛之后的净胜球排,净胜球高的排前面

4.净胜球相同,则按进球数多的排前面

5.如果进球数都相同,则名字字典序小的排前面(不用考虑失球数了,因为净胜球数,进球数都相同的话,失球数一定相同的)

6.保证球队名字各异,所以6场比赛结束后,排名是可以唯一确定的

模拟过程

1.得到了5场比赛的信息,那么先录入,并且处理好,然后按上面的规则排序。

记住一点:最后一场比赛,是保证BERLAND一定胜利的!!!!!

2.看看BERLAND在5场比赛后排在哪里

  如果是前2名,又因为最后一场比赛一定是BERLAND胜利,所以无论对手是谁,结束后BERLAND一定是前2名,所以要保证最后一场净胜球最少,失球最少,所以结果是1:0

3.如果不是排在前2名

  和第2名的积分差大于3,那么这场比赛BERLAND胜利,得到3积分,最后积分还是无法超过第2名,所以无论怎么胜利都不行了,输出IMPOSSIBLE

  如果和第2名的积分差小于3,且这场球一定是BERLAND赢的,那么赢了之后得3积分,一定超过第2名,所以比分只需要1:0

  如果和第2名的积分等于3,那么这种情况是一定有解的,因为保证是BERLAND赢,那么积分就会 = 第二名的积分 , 只要赢球赢得比较猛,就可以在净胜球等方面超过对方,就可以保证在

然后以第2名为目标,枚举最后一场比赛的净胜球,每次枚举,就改变球队的信息,然后重新排序,看看是否能排在前2名,直到可以为之

要注意枚举最后一场的净胜球,处理不好会掉进死循环,要设置一个条件让它break,具体看代码

代码写得不好,太长了

/*
排名规则
1.先按积分排名,赢球得3分,平局得1分,输球得0分
2.如果两球积分相同,看净胜球,净胜球高的排前面。
  净胜球=进球数-失球数
3.净胜球数相同的,进球数高的排前面
4.进球数都相同的,队名字典序小的排前面

输出,要保证berland
*/

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 10
#define LEN 25

const char T[LEN]="BERLAND";

bool g[N][N];
struct team{
   char name[LEN];
   int point;
   int diff;
   int score;
   int miss;
}a[N];
int tot;


int cmp(struct team x ,struct team y)
{
   if(x.point == y.point)
   {
      if(x.diff == y.diff)
      {
         if(x.score == y.score)
            return strcmp(x.name , y.name) < 0;
         return x.score > y.score;
      }
      return x.diff > y.diff;
   }
   return x.point > y.point;
}

int search_team(char *str)
{
   for(int i=0; i<tot; i++)
      if(!strcmp(str , a[i].name))
         return i;
   strcpy(a[tot].name , str);
   return tot++;
}

void fun(int pa  , int pb)  //本队不在前2名
{ //本队在本次比赛中一定是胜利的

   //BERLAND已经是前两位了,而且比赛一定是胜利,那么比赛后也一定是在前两位,比赛结果直接判断为1:0
   if(pa <= 1)
   { printf("1:0\n"); return ; }

   //就算胜利得到3积分也不能升到第2位
   if(a[1].point - a[pa].point > 3)
   { printf("IMPOSSIBLE\n"); return ;}

   //因为一定是赢球的,一定得3积分,那么一定超过了第2名
   if(a[1].point - a[pa].point < 3)
   { printf("1:0\n"); return ;}


   //剩下来的情况就是,第二名比自己多3积分,自己一定赢,赢了之后积分至少与第2名相同的

   int D = a[1].diff - a[pa].diff; //和第二名的净胜球差差

   //还没打之前,我们队的净胜球就大于等于第2名了,那么打了之后净胜球一定大于它,我方胜
   if(D <= 0)
   { printf("1:0\n"); return ;  }


   //剩下来就是净胜球不够第2名大,那么就枚举比赛我方的净胜球
   int k , d , p , q ;
   struct team b[N];
   for(d=(D+1)/2; ; d++) //净胜球数
      for(p=d; ; p++) //我方进球数
      {
         q = p - d; //对方进球数
         for(k=0; k<4; k++) b[k] = a[k];
         b[pa].diff += d;  b[pa].score += p;  b[pa].miss += q;  b[pa].point += 3;
         b[pb].diff -= d;  b[pb].score += q;  b[pb].miss += p;
         sort(b,b+4,cmp);
         for(k=0; k<4; k++)
            if(!strcmp(b[k].name , T))
               break;
         if(k<=1)
         { printf("%d:%d\n",p,q);  return ;}
         if(b[k].diff < b[1].diff) break;
      }
}

void solve()
{
   int x ,y;
   char temp[LEN],teama[LEN],teamb[LEN];
   for(int i=0; i<4; i++)
      for(int j=0; j<4; j++)
         if(i!=j && !g[i][j])
         {
            x = i;
            y = j;
            break;
         }
   strcpy(teama,a[x].name);
   strcpy(teamb,a[y].name);
   if(!strcmp(teamb,T))
   {
      strcpy(temp,teama);
      strcpy(teama,teamb);
      strcpy(teamb,temp);
   }
/*找出了还没最后一场比赛的两个队伍,并且让teama是BERLAND*/

   sort(a,a+4,cmp);

//   printf("%s    %s\n",teama,teamb);
//   for(int i=0; i<tot; i++)
//      printf("%s  point=%d  diff=%d  score=%d  miss=%d\n",
//      a[i].name,a[i].point,a[i].diff,a[i].score,a[i].miss);

   int pa = search_team(teama);
   int pb = search_team(teamb);
   fun(pa , pb); //BERLAND不在前两位,另外处理
}

int main()
{
   tot = 0;
   memset(a,0,sizeof(a));
   memset(g,false,sizeof(g));
   for(int i=1; i<=5; i++)
   {
      char s1[LEN],s2[LEN];
      int p,q;
      scanf("%s%s%d:%d",s1,s2,&p,&q);
      int x = search_team(s1);
      a[x].score += p;
      a[x].miss += q;
      a[x].diff = a[x].score - a[x].miss;
      int y = search_team(s2);
      a[y].score += q;
      a[y].miss += p;
      a[y].diff = a[y].score - a[y].miss;

      if(p > q) a[x].point += 3;
      else if(p == q)
      {
         a[x].point += 1;
         a[y].point += 1;
      }
      else  a[y].point += 3;
      g[x][y] = g[y][x] = true;
   }
   solve();
   return 0;
}
原文地址:https://www.cnblogs.com/scau20110726/p/3048153.html