IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 奶牛排队拍照 -> 正文阅读

[C++知识库]奶牛排队拍照

农夫约翰在给他编号为 1…N 的 N 头奶牛排队拍照。

约翰一开始计划从左向右数第 i 个位置排编号为 ai 的奶牛,他在一张纸上写下了排列 a1,a2,…,aN。

不幸的是,这张纸刚刚被小偷偷走了!

幸好约翰仍然有机会恢复他之前写下的排列。

在这张纸被偷走之前,奶牛贝茜记录了序列 b1,b2,…,bN?1,对于每一个 1≤i<N 满足 bi=ai+ai+1。

基于贝茜的信息,帮助约翰恢复可以产生序列 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。

数据范围
2≤N≤103

样例
输入样例:
5
4 6 7 6
输出样例:
3 1 5 2 4
样例解释
a 能够产生 b,因为 3+1=4,1+5=6,5+2=7,2+4=6。

思路一:枚举

感觉就是个暴力,因为从题意来看只要确定第一头剩下的都能确定
则我们只需要枚举第一头即可

(暴力枚举) 实际运行小于 O(n3)

时间复杂度
参考文献
C++ 代码

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1e5+10;
int n;
int a[N],b[N],s[N];
int main()
{
    cin>>n;
    bool flag=false;
    for (int i = 0; i < n-1; i ++ )cin>>b[i];
    for (int i = 1; i <= n; i ++ )
    {
        memset(s, 0, sizeof s);
        a[0]=i;//从1开始枚举
        s[i]=1;//标记
        for (int j = 0; j < n-1; j ++ )
        {
            int x=b[j]-a[j];//a[j+1]的可能值
            if(x<=0||s[x])break;
            else 
            {
                a[j+1]=x;//赋值
                s[x]++;
                if(j+1==n-1)//a数组存在,因为是从小开始枚举,此时一定是字典序最小
                {
                    for (int i = 0; i < n; i ++ )
                    cout<<a[i]<<' ';
                    return 0;
                }
            }
        }
    }
    return 0;
}

Java 代码

import java.io.*;
import java.util.*;
public class Main {
    static int n;
    public static void main(String args[])  {
      Scanner cin = new Scanner(System.in); 
       int a[]=new int [10100];
       int b[]=new int [10100];
       int s[]=new int [10100]; 
        n=cin.nextInt();
        boolean flag=false;
        for(int i=0;i<n-1;i++)b[i]=cin.nextInt();
        for(int i=1;i<=n;i++)
        {
            Arrays.fill(s, 0);
            a[0]=i;
            s[i]=1;
            for(int j=0;j<n-1;j++)
            {
                int x=b[j]-a[j];//a[j+1]的可能值
                if(x<=0||s[x]>0)break;
                else 
                {
                    a[j+1]=x;
                    s[x]++;
                    if(j+1==n-1)
                    {
                        for (int k = 0; k < n; k ++ )
                        System.out.print(a[k]+" ");
                        return ;
                    }
                }
            }
        }
    }
}

思路二:set+枚举

公式变形?
b2=a2+a3 b3=a3+a4
b3-b2=a4-a2 a2–>已知 b2-b1=a3-a1–> a3=b2-b1+a1
a数组里不能有重复的元素,那就用set容器存储某些结果

时间复杂度 O(n^2)
参考文献
C++ 代码

#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <set>
using namespace std;
int n;
int main()
{
    cin>>n;
    std::vector<int> b(n+1),a(n+1);
    for(int i=1;i<n;i++)cin>>b[i];
    for(int x=1;x<=n;x++)
    {
        a[1]=x,a[2]=b[1]-x;
        for(int i=3;i<=n;i++)
            a[i]=a[i-2]+b[i-1]-b[i-2];
        bool flag=false;
        set<int> s;
        for(int i=1;i<=n;i++)
        if(a[i]>=0&&a[i]<=n)
            s.insert(a[i]);
        if (s.size()==n)
        {
            flag=true;
            break;
        }
        s.clear();
    }
     for(int i=1;i<=n;i++)
        cout<<a[i]<<" ";
    return 0;
}

其他人的解法

Python3 代码


def main():
    n = int(input())
    b = list(map(int, input().split()))

    a = [0 for _ in range(n)]
    visited = [False for _ in range(n + 1)]
    for x in range(1, b[0]):
        a[0] = x
        ok = True
        for i in range(n + 1):
            visited[i] = False
        for i in range(1, n):
            a[i] = b[i - 1] - a[i - 1]
            if 1 <= a[i] <= n and visited[a[i]] == False:
                visited[a[i]] = True
            else:
                ok = False
                break
        if ok == True:
            for x in a:
                print(x, end = " ")
            print()
            return 

if __name__ == "__main__":
    main()

方法三:思路类似 暴力枚举

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1e6+10;
int n;
int b[N],a[N];
bool st[N];
bool get(int u)
{
    memset(st, 0, sizeof st);
    st[u]=true;
    a[1]=u;
    for (int i = 1; i < n; i ++ )
    {
        a[i+1]=b[i]-a[i];
        if(a[i+1]<1||a[i+1]>n||st[a[i+1]])return false;
        st[a[i+1]]=true;
    }
    return true;
}
int main()
{
    cin>>n;
    for(int i=1;i<n;i++)cin>>b[i];
    for(int i=1;i<=n;i++)
    {
        if(get(i))break;
    }
    for (int i = 1; i <= n; i ++ )
    cout<<a[i]<<' ';
    return 0;
}

方法四:dfs

大佬的解法

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1010;
int n , a[N] , b[N];
bool st[N];
bool dfs(int idx){  //idx为当前枚举的位置
    if(idx==n)return true;//第一次出来的就是字典序最小的了
    for (int i = 1; i <= b[idx]; i ++ ) //枚举a[idx]可能的大小
    if(!st[i] && a[idx-1]+i==b[idx]){   //i这个数字没有出现过 和 前面确定的数字和目前数字和为b[idx]
        st[i]=true;
        a[idx]=i;
        if(dfs(idx+1))return true;
        st[i]=false;
    }
    return false;
}
int main(){
    cin>>n;
    for (int i = 1; i <= n - 1; i ++ )scanf("%d",&b[i]);
    for (int i = 1; i <= b[1]; i ++ ){
        st[i]=true;
        a[0] =i;
        if(dfs(1)){
            for (int j = 0; j < n; j ++ )
                cout<<a[j]<<" ";
            return 0;
        }
        st[i]=false;
    }
}

欢迎留言点赞

嗷嗷嗷

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-02-14 20:56:33  更:2022-02-14 20:56:56 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 6:22:49-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码