USACO历年青铜组真题解析 | 2019年12月Livestock Lineup

学习C++从娃娃抓起!记录下USACO(美国信息学奥赛)备考青铜组别比赛学习过程中的题目,记录每一个瞬间。

附上汇总贴:USACO历年青铜组真题解析 | 汇总-CSDN博客


【题目描述】

每天,Farmer John 都要给他的 88 头奶牛挤奶。她们的名字分别是 Bessie,Buttercup,Belinda,Beatrice,Bella,Blue,Betsy,和 Sue。

不幸的是,这些奶牛相当难以伺候,她们要求 Farmer John 以一种符合 N 条限制的顺序给她们挤奶。每条限制的形式为“X 必须紧邻着 Y 挤奶”,要求奶牛 X 在挤奶顺序中必须紧接在奶牛 Y 之后,或者紧接在奶牛 Y 之前。

请帮助 Farmer John 求出一种满足所有限制的奶牛挤奶顺序。保证这样的顺序是存在的。如果有多种顺序都满足要求,请输出字典序最小的一种。也就是说,第一头奶牛需要是所有可能排在任意合法奶牛顺序的第一位的奶牛中名字字典序最小的。在所有合法的以这头字典序最小的奶牛为首的奶牛顺序中,第二头奶牛需要是字典序最小的,以此类推。

【输入】

输入的第一行包含 N。以下 N 行每行包含一句句子,以 "X must be milked beside Y" 的格式描述了一条限制,其中 X 和 Y 为 Farmer John 的某些奶牛的名字(上文列举了八个可能的名字)。

【输出】

请用 8 行输出一个奶牛的顺序,每行输出一头奶牛的名字,满足所有的限制。如果由多种顺序符合要求,输出字典序最小的奶牛顺序。

【输入样例】

3
Buttercup must be milked beside Bella
Blue must be milked beside Bella
Sue must be milked beside Beatrice

【输出样例】

Beatrice
Sue
Belinda
Bessie
Betsy
Blue
Bella
Buttercup

【代码详解】

#include <bits/stdc++.h>
using namespace std;
int n;
string a[9] = {"", "Bessie", "Buttercup", "Belinda", "Beatrice", "Bella", "Blue", "Betsy", "Sue"};
string b[10];
int book[10] = {0};
struct node {
    string x, y;
}p[10];
void dfs(int step)  // 排列模板
{
    if (step==8+1) {  // 排列退出条件
        int mark = 0;  // 定义标记位
        for (int i=1; i<=n; i++) {  // 遍历输入的n对相邻奶牛组合
            int pos1, pos2;  // 查找两头奶牛的位置
            for (int j=1; j<=8; j++) {  // 找到后赋值给pos1和pos2
                if (b[j]==p[i].x) pos1 = j;
                if (b[j]==p[i].y) pos2 = j;
            }
            if (abs(pos1-pos2)!=1) {  // 如果位置之差的绝对值不为1,说明不相邻
                mark = 1;  // 修改mark
                break;  // 退出循环,之后走到return
            }
        }
        if (mark == 0) {  // 如果两层循环下来确定n对奶牛都是相邻的,那说明符合条件
            for (int i=1; i<=8; i++) {  // 输出8头奶牛
                cout << b[i] << endl;  // 注意换行输出
            }
            exit(0);  // 退出程序
        }
        return;
    }
    for (int i=1; i<=8; i++) {  // 排列模板
        if (book[i]==0) {
            b[step] = a[i];  // 这里这里b[step]要赋值为选择的奶牛名称
            book[i] = 1;
            dfs(step+1);
            b[step] = "";  // 还原现场
            book[i] = 0;
        }
    }
}
int main()
{
    cin >> n;  // 输入n
    string tmp;  // 定义临时字符串,接受输入多个字符串中的无效信息
    for (int i=1; i<=n; i++) {  // 遍历n次输入
        cin >> p[i].x >> tmp >> tmp >> tmp >> tmp >> p[i].y;  // 记录相邻的奶牛组合
    }
    sort(a+1, a+8+1);  // 对于8个头奶牛的名字按照字典序排序(这样排列出来的,就一定是按照字典序最小的排前面)
    dfs(1);  // 排列模板
    return 0;
}

【运行结果】

3
Buttercup must be milked beside Bella
Blue must be milked beside Bella
Sue must be milked beside Beatrice
Beatrice
Sue
Belinda
Bessie
Betsy
Blue
Bella
Buttercup
  • 9
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
USACO2022金组是国际在线判系统USACO的最高级别,目难度较高,在该比赛中取得好成绩是一项巨大的成就。以下是对该比赛的一些解析。 第一:“交通计划” 目要求:给定一个n个节点的有向图,每条边有一个长度,希望添加最少的边使得所有节点连通,求最小生成树的权值和。 解析:该可以使用Kruskal算法求解,将每条边按权值从小到大排序,再依次加入,判断加入的边是否会形成环,若形成则不加入,直到所有节点连通为止。此时Kruskal算法得到的最小生成树的权值和即为所求。 第二:“点火计划” 目要求:给定一个n个节点的有向图,每条边有一个权值和一个点火时长,每个节点有一个点火启动时刻和时刻结束时刻,希望从其中选出一些边点火,使得所有节点都可从点火的边出发到达,且所选点火边的总点火时长最小。 解析:该可以使用最小费用最大流算法求解。将每条边看做一个容量为1,费用为点火时长的边,源点向节点的点火边容量为1,费用为0的边,节点的点火边向汇点的容量为1,费用为0的边,对这个网络进行最小费用最大流即可得到所选边的总点火时长最小。 第三:“美味佳肴” 目要求:给定n个菜品,每个菜品有它的权值和两个类别,希望选出k个菜品,使得选出的菜品数量在每个类别中都不超过$\frac{k}{3}$个,且所选菜品的权值和最大。 解析:该可以使用动态规划求解。设$f[i][j][k]$表示前i个菜品中,选择j个一类菜品,选择k个二类菜品的最大权值和,状态转移方程为$f[i][j][k]=max(f[i-1][j][k],f[i-1][j-1][k]+a[i],f[i-1][j][k-1]+b[i])$,其中a[i]为i号菜品的权值,若为一类则为该权值,否则为0,b[i]为i号菜品的权值,若为二类则为该权值,否则为0。最终答案为$f[n][$k/3$][$k/3$]。 以上是对USACO2022金组的部分目的解析USACO比赛是全球范围内的计算机竞赛,竞争非常激烈,能够在该比赛中脱颖而出是一项非常棒的成就。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值