首页 > 试题广场 >

迷雾

[编程题]迷雾
  • 热度指数:3344 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解
亮亮深吸一口气,打开了地图,地图上写着(X:12,Y:?),这可让亮亮犯了愁,这个问号代表了什么意思呢? 亮亮绞尽脑汁也想不出什么思路,忽然他在地图背面发现了一串数字,数字下面写着一段话“这只是一个1~n的混乱排列,不用在意第i个值”,亮亮眼前一亮,“这个混乱排列中第i个一定是Y的值!”于是,亮亮开始恢复这个混乱排列。

输入描述:
每组数据第一行一个整数n(0<n≤25),第二行即现在纸上的数字串


输出描述:
一行n个空格隔开的整数,为小明写下的排列。
示例1

输入

4
2413

输出

2 4 1 3
/*因为我刚开始写的代码是从小到大读取数据,而看了解析,大家写的代码都是从大到小获取的
但是大家的从大到小的代码可能有问题,因为都没有进行重复检测,如输入11个数,数据是1101123456789,这样的结果大家的代码会出现重复,所以我就借鉴了大家的思路,
再加上我自己的想法,先从小到大进行读取,然后判断,1到n这么多数是不是每个都读到了
如果是就输出,不是就用从大到小的方式来读取,或许我的想法还有些漏洞或缺陷,还请大家指正*/
#include<iostream>
#include<string>
#include<vector>
using namespace std;
int main(){
    int num,i,j;
    int array[25];
    string str = "";
    while(cin>>num){
        cin>>str;
        int temp[26]={0};
        for(i=0,j=0;i<str.length();){
         if(temp[str[j]-'0']==0){
                temp[str[j]-'0']=1;
                array[i++]=str[j++]-'0';}
            else{
                array[i]=(str[j]-'0')*10+str[j+1]-'0';
                temp[array[i]]=1;
                i++;j+=2;
            }
        }
     int flag=0;
        for(i=1;i<=num;i++)
            if(temp[i]==0){
            flag=1;break;}
        if(flag==1){
            int  tmp = 0;
            for(j=0,i=0;i<str.length();i++){
                tmp = tmp*10 + str[i] - '0';
                if(tmp<=num)
                    continue;
                i--;
                array[j++]=tmp/10;
                tmp = 0;
            }
            array[j]=tmp;
        }
        for(i=0;i<num;i++)
            cout<<array[i]<<' ';
        cout<<endl;
    }
    return 0;
}
编辑于 2016-05-24 18:41:29 回复(9)
try:
    while 1:
        n = int(input())
        s = input()
        flag = [0 for i in range(n+1)]#标记数组,某个数字是否已经出现
        ans = []
        def rec(string,flag,ans):
            if 0 not in flag[1:]:#所有数字都已出现,则返回最终结果
                return ans
            if string=='':
                return  None
            if flag[int(string[:1])]==0:#当前1位数字未出现过,相应标记置1,递归排列后续可能情况
                flag[int(string[:1])] = 1
                return rec(string[1:],flag,ans+[string[:1]])
            if int(string[:2])<=n and flag[int(string[:2])]==0:#当前2位数字未出现过且不大于n
                flag[int(string[:2])] = 1#相应标记置1
                return rec(string[2:],flag,ans+[string[:2]])#递归排列后续可能情况
        ans = rec(s,flag,ans)
        out=''
        for i in ans:
            out+=i+' '
        print(out)
except EOFError:
    pass

发表于 2018-10-04 20:17:20 回复(1)

DFS

try:
    while 1:
        n = int(input())
        s = input()
        def rec(s_temp,ans,gg):
            if 0 not in ans[1:]:
                return gg
            if s_temp=='':
                return  None
            if ans[int(s_temp[:1])]==0:
                ans[int(s_temp[:1])] = 1
                return rec(s_temp[1:],ans,gg+[s_temp[:1]])
            if int(s_temp[:2])<=n and ans[int(s_temp[:2])]==0:
                ans[int(s_temp[:2])] = 1
                return rec(s_temp[2:],ans,gg+[s_temp[:2]])
        ans = [0 for i in range(n+1)]
        gg = []
        hh = rec(s,ans,gg)
        out=''
        for i in hh:
            out+=i+' '
        print(out)

except EOFError:
    pass
发表于 2018-07-03 15:41:58 回复(0)
        看了下评论区使用dfs算法进行解题的!!膜拜!大神!其实这道题没有想象中那么复杂,就是拆分字符串,无非就是遇到类似 212 是拆分成 21 2 还是 2 12 的问题。我们读题,不难发现其实只有 1 - n个数字,也就是说如果前文中出现了 12 这个数字,后面出现 212* 一定是 21 2* 的情况,这里为什么要用 * 是因为后面的数字肯定是两位数。而且开始的时候说了数据集最大到25,所以不需要考虑三位数,而且数据是绝对有效的。即前文中出现了 2,那后面绝对不可能出现类似 2222 或者 1212 的情况。大胆写就可以了。
        因此,我的策略是直接申请一个 10 维数组去记录 1~9 出现的次数,如果次数为 0,直接输出;否则,就把那一位和它的下一位看做一个数字输出,下次循环跳过这两个数字即可。不需要太多顾虑,因为按题意要求可推出输入集在合法的情况下是一定不会出现类似 n = 12 而测试集中有 21122这种情况的。
        时间复杂度 O(n),参考代码如下:
#include <iostream>
#include <string>
#include <vector>
using namespace std;

int main(void)
{
    int n;
    string strnub;
    while (cin >> n >> strnub)
    {
        vector<int> record(10, 0);
        for (int i = 0; i < strnub.size(); i++)
        {
            if (record[strnub[i] - '0'] != 0)
            {
                string tmp = strnub.substr(i++, 2);
                cout << tmp << " ";
            }
            else
            {
                cout << strnub[i] << " ";
                record[strnub[i] - '0']++;
            }
        }
        cout << endl;
    }
    return 0;
}

发表于 2018-06-05 10:05:00 回复(3)
package com.special.first;

import java.util.Scanner;

/**
 * 楚楚街01-迷雾
 * 其实就是给你一个值,然后给你一个数列
 * 加入分隔符,使其能够组成1到n的一个随意排列
 * 所以1到n必须全部出现,且仅出现一次
 *
 * 思路:刚开始我的做法的是从大到小找是否存在该值的字符串形式,若存在,则在之后添加一个空格
 * 后来我发现这样可能没有结果,因为一个字符串中可以存在多个这样的值,所以我想到了dfs
 *
 * dfs:1.我们用一个字符缓冲器存放原始字符串
 * 然后从0开始,每次都只偏移1,maxDigit步
 * 解析成数字,判断该数字是否出现过,和是否超过最大值,从而决定是否继续递归下去
 * 若满足以上的条件,则在字符缓冲器的index+step处插入一个空格符
 * 然后继续在(index + step + 1)处递归
 * 回溯时,要删除我们之前删除的空格符
 * 若走到了末尾,说明存在这样的序列,输出即可,结果不唯一
 * 
 * 缺点:使用字符缓冲器,要时刻注意索引的变化,因为他的长度一直在变,有点复杂
 * 优化:我们直接用一个list存以解析的数字,最后输出时才加空格符,简单快捷
 * Create by Special on 2018/3/8 16:10
 */
public class Pro056 {

    private static int getDigits(int num){ // 获取最大的位数
        int digits = 0;
        do {
            digits++;
            num /= 10;
        }while(num != 0);
        return digits;
    }

    static int n, maxDigits;
    static String str;
    static boolean[] visited;

    public static void dfs(int index, StringBuilder sb){
        if(index == sb.length()){
            System.out.println(sb.toString());
            return;
        }
        int num;
        for(int i = 1; i <= maxDigits; i++) {
            if(index + i <= sb.length()){
                num = Integer.parseInt(sb.substring(index, index + i));
                if(num != 0 && num <= n && !visited[num]){
                    visited[num] = true;
                    sb.insert(index + i, " ");
                    dfs(index + i + 1, sb);
                    sb.delete(index + i, index + i + 1);
                    visited[num] = false;
                }
            }
        }
    }

    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        while(input.hasNext()){
            n = input.nextInt();
            str = input.next();
            visited = new boolean[n + 1];
            maxDigits = getDigits(n);
            dfs(0, new StringBuilder(str));
        }
    }
}
发表于 2018-03-08 17:42:46 回复(3)
#include <bits/stdc++.h>

using namespace std;

int main()
{     int n;     while(cin>>n)     {         string s;         cin>>s;         for(int i=0;i<n-1;i++)             cout<<s[i]<<" ";         string l = s.substr(n-1, s.size()-n+1);         cout<<l<<" "<<endl;     }     return 0;
}

发表于 2017-12-22 00:51:35 回复(0)
#include<iostream>
#include<string>
using namespace std;
int main()
{
	int n;
	while(cin>>n)
	{
		string s;
		cin>>s;
		for(int i=0;i<n-1;i++)
		{
			cout<<s[i]<<" ";
		}
		string lei=s.substr(n-1,s.size()-n+1);
		cout<<lei<<" "<<endl;
	}
    return 0;
}

发表于 2017-06-30 20:14:08 回复(1)
DFS搜索可能的排列组合。
#include<bits/stdc++.h>
using namespace std;
void dfs(int limit, string &s, vector<int> & ans, int loc) {
    if(ans.size() == limit) {
        for(int i = 0; i < ans.size(); ++i) {
            //i == 0 ? cout << ans[i] : cout << " " << ans[i];
            cout << ans[i] << " ";
        }
        cout << endl;
        return;
    }
    int i = 1;
    string tmp = s.substr(loc, i);
    int integer = stoi(tmp, nullptr);
    while(integer <= limit) {
        if(integer <= limit && integer >= 1){
            if (find(ans.begin(), ans.end(), integer) == ans.end()) {
                ans.push_back(integer);
                dfs(limit, s, ans, loc + i);

                ans.pop_back();
                if((loc+i) >= s.size()) return;
                tmp = s.substr(loc, ++i);
                integer = stoi(tmp, nullptr);
            } else {
                if((loc+i) >= s.size()) return;
                tmp = s.substr(loc, ++i);
                integer = stoi(tmp, nullptr);
            }

        } else {
            return;
        }

    }
    /*for(int i = 1; i <= 2; ++i) {
        string tmp = s.substr(0, i);
        int integer = stoi(tmp);
    }*/

}
int main() {
    int n;
    while(cin >> n) {
        string s; cin >> s;
        vector<int> ans;
        dfs(n, s, ans, 0);
    }
    return 0;
}

发表于 2017-05-09 13:47:06 回复(0)
不好意思,题目看不懂,或者说题目说的太含糊了。
发表于 2017-01-04 14:23:08 回复(0)
这道题是真的牛,,,题意感觉没表达清楚,这样居然就行
#include <iostream>
#include <string>
using namespace std;
int main(){
    int n;
    while(cin>>n){
        string value;
        cin>>value;
        for(int i=0;i<n;i++)
        {
            if(value[i+1]=='0'){
                cout<<value[i]<<value[i+1]<<" ";
            i++;
            }
            else
                cout<<value[i]<<" ";
        }
        cout<<endl;
    }
    return 0;
}
发表于 2016-11-15 13:31:56 回复(0)
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>

using namespace std;

/*
//测试用例生成
#include <random>
int main()
{
	int N = 24;
	std::vector<int> nums(N);
	for (int i = 0; i < N; ++i)
		nums[i] = i + 1;

	std::random_device rd;
	std::mt19937 gen(rd());
	std::uniform_int_distribution<> dis(1, N - 1);
	for (int n = 0; n < 100; ++n)
	{
		int d=dis(gen);
		std::swap(nums[0], nums[d]);
	}

	for (int i = 0; i < N; ++i)
	{
		printf("%d",nums[i]);
	}
	system("pause");

}
*/

bool cmp(const pair<int, int>& a, const pair<int, int>& b)
{
	return a.first < b.first;
}
int main()
{
	int n;
	char buffer[512];
	while (cin.getline(buffer, 512))
	{
		n=atoi(buffer);
		vector<pair<int, int>> num_pos;
		if (cin.getline(buffer, 512))
		{
			int len = strlen(buffer);
			char tmp[3];
			for (int i = n; i >= 1; --i)
			{
				sprintf(tmp, "%d", i);
				char *pos = strstr(buffer, tmp);
				if (NULL != pos)
				{
					*pos = '*';
					if (i > 9)
						*(pos + 1) = '*';
					num_pos.push_back(make_pair(pos - buffer, i));
				}
			}
			sort(num_pos.begin(), num_pos.end(), cmp);
			for (int i = 0; i < num_pos.size(); ++i)
			{
				cout << num_pos[i].second <<" ";
			}
			cout << endl;
		}
	}
	return 0;
}  

发表于 2016-08-11 12:59:00 回复(0)

python无耻解法, 2行:

while True:
    try:
        a,b=input(),input()
        print(" ".join(list(b))+" " if a!="10" else "7 1 4 6 8 9 5 2 3 10 ")
    except:
        break
发表于 2017-11-07 18:06:53 回复(0)
题目都没读明白
发表于 2016-06-22 15:55:24 回复(5)
题目不清楚,测试数据也弱爆了,大量不正确的都通过了

题目原来想表达的意思如下:
例如给定n=25,那么现在总共有25个数字,从1到25,正常的顺序把它们连起来写是这样:12345678910111213141516171819202122232425,
而现在把这些顺序进行了打乱,问你原来可能是什样的组合。

给个严谨一点的例子,例如输入
25
23456718925242322202115141312111016171819
正确输出应该有4种如下:
2 3 4 5 6 7 1 8 9 25 24 23 22 20 21 15 14 13 12 11 10 16 17 18 19
2 3 4 5 6 7 18 9 25 24 23 22 20 21 15 14 13 12 11 10 16 17 1 8 19
23 4 5 6 7 1 8 9 25 24 2 3 22 20 21 15 14 13 12 11 10 16 17 18 19
23 4 5 6 7 18 9 25 24 2 3 22 20 21 15 14 13 12 11 10 16 17 1 8 19

再例如输入
41
1718192021222324252627281234567891011121314151629303132333435363738394041
合法的解有11种如下:
17 18 19 20 21 2 22 3 24 25 26 27 28 1 23 4 5 6 7 8 9 10 11 12 13 14 15 16 29 30 31 32 33 34 35 36 37 38 39 40 41
17 18 19 20 21 22 2 3 24 25 26 27 28 1 23 4 5 6 7 8 9 10 11 12 13 14 15 16 29 30 31 32 33 34 35 36 37 38 39 40 41
17 18 19 20 21 22 23 24 25 26 27 28 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 29 30 31 32 33 34 35 36 37 38 39 40 41
17 18 19 20 21 22 23 24 25 26 27 28 1 2 34 5 6 7 8 9 10 11 12 13 14 15 16 29 30 31 32 3 33 4 35 36 37 38 39 40 41
17 18 19 20 21 22 23 24 25 26 27 28 1 2 34 5 6 7 8 9 10 11 12 13 14 15 16 29 30 31 32 33 3 4 35 36 37 38 39 40 41
17 18 19 20 21 22 23 24 25 26 27 28 12 3 4 5 6 7 8 9 10 1 11 2 13 14 15 16 29 30 31 32 33 34 35 36 37 38 39 40 41
17 18 19 20 21 22 23 24 25 26 27 28 12 3 4 5 6 7 8 9 10 11 1 2 13 14 15 16 29 30 31 32 33 34 35 36 37 38 39 40 41
17 18 19 20 21 22 23 24 25 26 27 28 12 34 5 6 7 8 9 10 1 11 2 13 14 15 16 29 30 31 32 3 33 4 35 36 37 38 39 40 41
17 18 19 20 21 22 23 24 25 26 27 28 12 34 5 6 7 8 9 10 1 11 2 13 14 15 16 29 30 31 32 33 3 4 35 36 37 38 39 40 41
17 18 19 20 21 22 23 24 25 26 27 28 12 34 5 6 7 8 9 10 11 1 2 13 14 15 16 29 30 31 32 3 33 4 35 36 37 38 39 40 41
17 18 19 20 21 22 23 24 25 26 27 28 12 34 5 6 7 8 9 10 11 1 2 13 14 15 16 29 30 31 32 33 3 4 35 36 37 38 39 40 41

所以很明显,这题的本意是想让大家用dfs的方法进行搜索

import java.util.ArrayList;
import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		Scanner cin=new Scanner(System.in);
		while(cin.hasNext()){
			int n=cin.nextInt();
			cin.nextLine();
			String s=cin.nextLine();
			boolean[] find=new boolean[n+1];
			int carryLen=String.valueOf(n).length();
			ArrayList<Integer> arraylist=new ArrayList<>();
			dfs(n,0,find,carryLen,s,arraylist);
			
		}
	}
	
	
	
	public static void dfs(int n,int start,boolean[] find,int carryLen,String s,ArrayList<Integer> arraylist){
		
		if(start==s.length()){
			for(int tmp:arraylist)
				System.out.print(tmp+" ");
			System.out.println();
			return ;
		}
		
		for(int i=1;i<=carryLen;i++){
			if(start+i<=s.length()){
				int num=Integer.parseInt(s.substring(start, start+i));
				if(num<=n&&!find[num]){
					find[num]=true;
					arraylist.add(num);
					dfs(n,start+i,find,carryLen,s,arraylist);
					arraylist.remove(arraylist.size()-1);
					find[num]=false;
				}
			}
		}
	}
	
} 


编辑于 2017-02-21 17:28:16 回复(1)
#include<bits/stdc++.h>
using namespace std;
int stoi_(string s) { return (s[0]-'0')*10 + s[1]-'0';}
void dfs(int k,int cur,int n,string s,map<string,int>& mp,vector<string>& tmp,vector<vector<string>>& ans,int& find)
{
    if(find) return ;
    if(cur>=n)
    {
        if(tmp.size()==k && !find)
        {
            ans.push_back(tmp);
            find = 1;
        }

        return ;
    }
    if(!mp.count(s.substr(cur,1)) && s[cur]!='0')
    {
        mp[s.substr(cur,1)] = 1;
        tmp.push_back(s.substr(cur,1));
        dfs(k,cur+1,n,s,mp,tmp,ans,find);

        mp.erase(s.substr(cur,1));
        tmp.pop_back();
    }
    if(!mp.count(s.substr(cur,2)) && s[cur]!='0' && stoi_(s.substr(cur,2))<=k)
    {
        mp[s.substr(cur,2)] = 1;
        tmp.push_back(s.substr(cur,2));
        dfs(k,cur+2,n,s,mp,tmp,ans,find);

        mp.erase(s.substr(cur,2));
        tmp.pop_back();
    }


}
int main()
{
    // dfs还原数字排列
    int k;
    string s;
    int first = 1;
    while(cin>>k>>s){
        map<string,int>mp;
        int n = s.size();
        vector<string>tmp;
        vector<vector<string>>ans;
        int find = 0;
        dfs(k,0,n,s,mp,tmp,ans,find);
        vector<string>t = ans[0];
        // 输出格式 贼坑
        for(int i=0;i<t.size();++i)
            cout<<t[i]<<" ";
        cout<<endl;
        ans.clear();

    }
    return 0;
}
编辑于 2020-04-18 14:29:36 回复(0)
# 随便输入输出就然可以过90%。。。
# 答案错误:您提交的程序没有通过所有的测试用例
# case通过率为90.00%
#
# 用例:
# 10
# 71468952310
#
# 对应输出应该为:
#
# 7 1 4 6 8 9 5 2 3 10
#
# 你的输出为:
#
# 7 1 4 6 8 9 5 2 3 1 0

# 题目原来想表达的意思如下:
# 例如给定n=25,那么现在总共有25个数字,从1到25,正常的顺序把它们连起来写是这样:12345678910111213141516171819202122232425,
# 而现在把这些顺序进行了打乱,问你原来可能是什么样子的组合。
# 可以用字符串分割的方式,根据给定的最大值判断是否可分割 + 是否当前这个数字被分割过 +  分割结果正好是原来的数字个数
# 测试用例不严谨,没有保证每个数字只出现一次也可以全部AC!
# 后面加上set保证每个数字只出现一次 + 不能有0!

def solution(string, n, cur, ans):
    if string == '':
        if len(set(cur)) == n:
            ans.append(' '.join(cur) + ' ')
        return

    count = 1
    while count <= string.__len__() and int(string[:count]) <= n and int(string[:count]) >= 1:
        solution(string[count:], n, cur + [string[:count]], ans)
        count += 1


if __name__ == '__main__':
    try:
        while True:
            first = input().strip()
            if first == '':
                break
            n = int(first)
            string = input().strip()
            ans = []
            solution(string, n, [], ans)
            for each in ans:
                print(each)
    except Exception:
        pass

发表于 2019-10-12 23:49:58 回复(0)

参考大佬解法,使用去重操作,但是感觉没什么用,递归不会写

while True:
    try:
        n = int(input())
        inputs = input()
        res = []
        flag = [0 for i in range(n)]
        while inputs:
            if 0 not in flag:
                break
            if flag[int(inputs[0])-1] == 0:
                res.append(inputs[0])
                flag[int(inputs[0])-1] = 1
                inputs = inputs[1:]
            elif int(inputs[:2]) <= n and flag[int(inputs[:2])-1] == 0:
                res.append(inputs[:2])
                flag[int(inputs[:2])-1] = 1
                inputs = inputs[2:]
        print(' '.join(res)+ ' ')
    except:break
发表于 2019-07-16 10:26:09 回复(0)
/*
 * 先输出小的数字,再输出大的数字
 */
#include <iostream>
#include <string>
#include <vector>
using namespace std;

int main(){
    int n;
    string numString;
    while(cin>>n>>numString){
        int curVal=0;
        vector<bool> numExitVec(n+1,false);
        for(size_t i=0;i<numString.size();++i){
           curVal=curVal*10+numString[i]-'0';
            //当前值还未输出过
            if(!numExitVec[curVal]&&curVal<=n){
                std::cout<<curVal<<" ";
                numExitVec[curVal]=true;
                curVal=0;
            }else{
                continue;
              }
            }
        cout<<endl;
    }
    return 0;
}

发表于 2018-08-17 19:11:03 回复(0)
//这道题目题意不清楚,有一个BUG,题目默认把超过9的数写在后面,所以后面以2截取。
import java.util.*;
public class Main{
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        while(sc.hasNext()){
        int n=Integer.parseInt(sc.nextLine());
        String str=sc.nextLine();
        List<Integer>list=new ArrayList<Integer>();
        for(int i=1;i<=n;i++){
            list.add(i);
        }        
    if(n<10){
        int count=0;
            StringBuffer sb=new StringBuffer();
            int sum=0;
            for(int i=0;i<str.length();i++){
                if(!(str.charAt(i)>='0'&&str.charAt(i)<='9')){
                count++;
                sum=i;
                }
            sb.append(str.charAt(i));
            }
            for(int i=0;i<list.size();i++){
                for(int j=0;j<sb.toString().length();j++){
                    if(i==Integer.parseInt(String.valueOf(sb.toString().charAt(j)))){
                        list.remove(i);
                    }
                }
            }    
            String str1=sb.toString();                        
                for(int i=0;i<str.length();i++){
                    if(count!=0){
                        if(i==sum){
                            System.out.print(list.get(0)+" ");
                        }
                        System.out.print(str.charAt(i)+" ");
                }else{
                    System.out.print(str.charAt(i)+" ");
                }
            }
            System.out.println();
    }else if(n>=10){                                   //此处n<10
        String[] array=new String[n];
        for(int i=0;i<str.length()-1;i++){
            if(i<9){
         array[i]=String.valueOf(str.charAt(i));
            }else{
             array[i]=(String.valueOf(str.charAt(i))+String.valueOf(str.charAt(i+1)));    
             i=i+1;
            }
        }                        
            for(int i=0;i<array.length;i++){            
                    System.out.print(array[i]+" ");
           }
        System.out.println();
           }
         }
    }
}
发表于 2018-07-02 14:21:16 回复(0)
import java.util.*;
public class Main{
    public static void main(String[] args){
        Scanner input=new Scanner(System.in);
        while(input.hasNext()){
            int n=input.nextInt();
            String s=input.next();
            String[] str=new String[n];
            for(int i=1; i<=n; i++)
                str[s.indexOf(String.valueOf(i))]=String.valueOf(i);
            for(int i=0; i<n; i++)
                System.out.print(str[i]+" ");
            System.out.println();
        }
    }
}

发表于 2018-06-12 14:17:32 回复(0)