学习C++从娃娃抓起!记录下USACO(美国信息学奥赛)备考青铜组别比赛学习过程中的题目,记录每一个瞬间。
附上汇总贴:USACO历年青铜组真题解析 | 汇总-CSDN博客
【题目描述】
Farmer John 在给他编号为 1…N 的 N 头奶牛排队拍照(2≤N≤10^3)。FJ 一开始计划从左向右数第 i 个位置排编号为 ai 的奶牛,他在一张纸上写下了排列 a1,a2,…,aN。不幸的是,这张纸刚刚被 Farmer Nhoj 偷走了!
幸好 FJ 仍然有机会恢复他之前写下的排列。在这张纸被偷走之前,Bessie 记录了序列 b1,b2,…,bN−1,对于每一个 1≤i<N 满足 bi=ai+ai+1。
基于 Bessie 的信息,帮助 FJ 恢复可以产生序列 b 的“字典序最小”的排列 a。排列 x 字典序小于排列 y,如果对于某个 j,对于所有 i<j 均有 xi=yi,且有 xj<yj(换句话说,这两个排列到某个位置之前都相同,在这个位置上 x 小于 y)。保证存在至少一个满足条件的 a。
【输入】
输入的第一行包含一个整数 N。
第二行包含 N−1 个空格分隔的整数 b1,b2,…,bN−1。
【输出】
输出一行,包含 N 个空格分隔的整数 a1,a2,…,aN。
扫描二维码关注公众号,回复:
17161619 查看本文章
【输入样例】
5
4 6 7 6
【输出样例】
3 1 5 2 4
【代码详解】
#include <bits/stdc++.h>
using namespace std;
int n, a[1005], b[1005], used[1005]; // 定义used数组判断数据是否重复
ifstream filein("photo.in");
ofstream fileout("photo.out");
int main()
{
filein >> n; // 输入n
for (int i=1; i<n; i++) { // 依次输入b数组的值
filein >> b[i];
}
for (int i=1; i<b[1]; i++) { // a1从1开始遍历,直至b[1],因为a2>0
a[1] = i; // 设置a[1]为i
for (int j=1; j<n; j++) { // 进行n-1次计算
a[j+1] = b[j] - a[j]; // 得到a[2] - a[n]的值
}
int mark = 0; // 定义mark用于判断a数组是否有效
memset(used, 0, sizeof(used)); // 每次初始化used数组
for (int i=1; i<=n; i++) { // 遍历n个值
if (a[i]<=0 || a[i]>n) { // 如果a[i]大于0或者大于n
mark = 1; // 判断无效
break; // 并结束循环
}
used[a[i]]++; // 否则进行统计
}
for (int i=1; i<=n; i++) { // 再次遍历n个值
if (used[i]>1) mark = 1; // 判断是否有数据重复
}
if (mark==1) continue; // 遇到不正确的,i递增,进行下一次查找
else break; // 找到第一个满足所有条件的就退出,此时a数据为字典序最小的结果
}
for (int i=1; i<n; i++) { // 打印a数组
fileout << a[i] << " ";
}
fileout << a[n]; // USACO判断最后一个数字之后不能有空格,所以单独处理a[n]
return 0;
}
【运行结果】
5
4 6 7 6
3 1 5 2 4