USACO历年青铜组真题解析 | 2020年1月Photoshoot

学习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。

【输入样例】

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

猜你喜欢

转载自blog.csdn.net/guolianggsta/article/details/134855555
今日推荐