2018 湖南多校(2)----CSU 2030 World Cup Draw (阅读理解题 + 蛮力DFS)

题目链接

 题意: 这题意很折腾人!(针对我这种code差还英文差的人!) 一共有32支队各自都有自己上季度的排名和自己属于的联盟;4个Seeding Pot
 (储存罐),由顶向底各有八个队名;从Pot1按顺序倒空所有Pot(罐子倒空,是从顶到底倒顺序倒得);倒出的每个队分入到8组中去(A—H组)。
   i) 同Pot队伍不能放入到相同的组去;(Pot里的队伍每个组放1个)
   ii) 除了UEFA联盟可以每组最多有两支队伍外,其它联盟最多只能有每组一支;(UEFA联盟有14支队伍)
    当前的拿出的队伍再确保满足上面规则且能分配好组的情况下,尽量分配到最左边的组,统计每个组里队伍的rank之和,按rank分数小的顺序且分数相同以组名的字典序顺序排序输出组名和rank和。

1、 队伍的上季度的排名和联盟号
 队伍的上季度的排名和联盟号

总共有5个联盟:
UEFA 14支、CONMEBOL 5支、 CONCACAF 3支、AFC 5支、CAF 5支;
我们需要用数据结构来存储这些关系,并且方便查询,队名是主键,知道队名需要快速查询:其所属联盟UNION和Rank,很明显我们用Map来实现非常方便,因为Map的下标idx可以为任意类型,不像数组仅仅只能用0……n自然数。

map <string,int> MapTR;
map <string, string> MapTU;
map <string,int> YS;

string UNION[]={
    "UEFA","UEFA","CONMEBOL","UEFA","CONMEBOL","UEFA","UEFA","UEFA",
    "UEFA","CONMEBOL","UEFA","UEFA","CONMEBOL","CONCACAF","CONMEBOL","UEFA",
    "UEFA","UEFA","CONCACAF","UEFA","CAF","CAF","CAF","AFC",
    "UEFA","CAF","AFC","AFC","CAF","CONCACAF","AFC","AFC"
};
int Rank[]={ 65,1,2,3,4,5,6,7,
             8,10,11,12,13,16,17,18,
             19,21,22,25,28,30,32,34,
             38,41,43,44,48,49,62,63
           };
string TEAM[]={
    "Russia", "Germany", "Brazil", "Portugal", "Argentina", "Belgium", "Poland", "France",
    "Spain", "Peru", "Switzerland", "England", "Colombia", "Mexico", "Uruguay", "Croatia",
    "Denmark", "Iceland", "Costa Rica", "Sweden", "Tunisia", "Egypt", "Senegal", "Iran",
    "Serbia", "Nigeria", "Australia", "Japan", "Morocco", "Panama", "South Korea", "Saudi Arabia"
};
//建立MapTR 、 MapTU对应关系
//建立YS对应联盟的排序标记
void init(){
    for(int i=0;i<32;++i){
        MapTR[TEAM[i]]=Rank[i];
        MapTU[TEAM[i]]=UNION[i];
    }

    YS["UEFA"]=1;
    YS["CONMEBOL"]=2;
    YS["CAF"]=3;
    YS["CONCACAF"]=4;
    YS["AFC"]=5;
}

2、 输入部分: 4个Pot且由顶到底循序输入队名,且两个队名之间有”, “(一个“,”后有一个空格,坑人的是队名会有空格,字符串输入;遍历字符串,不为‘,’,即添加至字符串a后(‘+’运算);遇到‘,’,遍历跳过后面的字符‘ ’,记录a为一个队伍名,并清空a;

void Read(){
    string a="\0";
    int len=s.length();
    for(int i=0;i<len;++i)
        if(s[i]==','){
            i++; team[num++]=a;
            a="\0";
        }else a+=s[i];

    team[num++]=a;
}

3、DFS模拟这个过程,从第一个队开始,从A到H队,枚举它所分配的位置,必须满足题目要求的两个条件,并往下继续DFS,如果失败,即证明它不能为此位置,继续往右遍历合适的位置,如果均不可,即证实前面的队伍放置有问题,向上回溯false,表明错误,更新前面的队伍的放法;如果一直DFS到rt=32,即证实已经找到答案了!

bool dfs(int rt){
    if(rt==32) return true;
    int Union= YS[MapTU[team[rt]]];
    for(int i=0;i<8;++i){
        if(vis[rt/8][i]||!isTrue(i,Union)) continue;
        vis[rt/8][i]=1;  flag[i][Union]+=1; val[i]+=MapTR[team[rt]];
        if(dfs(rt+1)) return true;
        vis[rt/8][i]=0;  flag[i][Union]-=1; val[i]-=MapTR[team[rt]];
    }
    return false;
}

代码:

/******************************************
  2018 湖南多校赛(2) 分组对赛---(DFS)
******************************************/
#include <iostream>
#include <fstream>
#include <stdio.h>
#include <string.h>
#include <stack>
#include <queue>
#include <vector>
#include <map>
#include <algorithm>
#define llt long long
using namespace std;

map <string,int> MapTR;
map <string, string> MapTU;
map <string,int> YS;

string UNION[]={
    "UEFA","UEFA","CONMEBOL","UEFA","CONMEBOL","UEFA","UEFA","UEFA",
    "UEFA","CONMEBOL","UEFA","UEFA","CONMEBOL","CONCACAF","CONMEBOL","UEFA",
    "UEFA","UEFA","CONCACAF","UEFA","CAF","CAF","CAF","AFC",
    "UEFA","CAF","AFC","AFC","CAF","CONCACAF","AFC","AFC"
};
int Rank[]={ 65,1,2,3,4,5,6,7,
             8,10,11,12,13,16,17,18,
             19,21,22,25,28,30,32,34,
             38,41,43,44,48,49,62,63
           };
string TEAM[]={
    "Russia", "Germany", "Brazil", "Portugal", "Argentina", "Belgium", "Poland", "France",
    "Spain", "Peru", "Switzerland", "England", "Colombia", "Mexico", "Uruguay", "Croatia",
    "Denmark", "Iceland", "Costa Rica", "Sweden", "Tunisia", "Egypt", "Senegal", "Iran",
    "Serbia", "Nigeria", "Australia", "Japan", "Morocco", "Panama", "South Korea", "Saudi Arabia"
};
//建立MapTR 、 MapTU对应关系
//建立YS对应联盟的排序标记
void init(){
    for(int i=0;i<32;++i){
        MapTR[TEAM[i]]=Rank[i];
        MapTU[TEAM[i]]=UNION[i];
    }

    YS["UEFA"]=1;
    YS["CONMEBOL"]=2;
    YS["CAF"]=3;
    YS["CONCACAF"]=4;
    YS["AFC"]=5;
}
string s,team[33];
int flag[10][7],vis[5][10],idx[10],val[10];
int num=0;

bool isTrue(int rt,int Union){
    return (flag[rt][Union]==0||(flag[rt][Union]==1&&Union==1));
}

bool dfs(int rt){
    if(rt==32) return true;
    int Union= YS[MapTU[team[rt]]];
    for(int i=0;i<8;++i){
        if(vis[rt/8][i]||!isTrue(i,Union)) continue;
        vis[rt/8][i]=1;  flag[i][Union]+=1; val[i]+=MapTR[team[rt]];
        if(dfs(rt+1)) return true;
        vis[rt/8][i]=0;  flag[i][Union]-=1; val[i]-=MapTR[team[rt]];
    }
    return false;
}

void Read(){
    string a="\0";
    int len=s.length();
    for(int i=0;i<len;++i)
        if(s[i]==','){
            i++; team[num++]=a;
            a="\0";
        }else a+=s[i];

    team[num++]=a;
}

bool cmp(int a,int b){return val[a]<val[b]||(val[a]==val[b]&&a<b);}
int main(){
    init();
    while(1){
        //freopen("out.txt","w",stdout);
        num=0;
        memset(val,0,sizeof(val));
        memset(flag,0,sizeof(flag));
        memset(vis,0,sizeof(vis));
        int t=0;
        for(int i=0;i<4;++i){
            getline(cin,s);
            if(s=="End") {t=1;break;}
            Read();
        }
        if(t) break;
        for(int i=0;i<8;++i) idx[i]=i;
        dfs(0);
        sort(idx,idx+8,cmp);
        for(int i=0;i<8;++i)
            cout<<(char)(idx[i]+'A')<<" "<<val[idx[i]]<<endl;
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值