hiho220 Push Button I

版权声明:转载我的原创博客情注明出处 https://blog.csdn.net/qq_31964727/article/details/82735619

hiho220 Push Button I

时间限制:5000ms

单点时限:1000ms

内存限制:256MB

描述

There are N buttons on the console. Each button needs to be pushed exactly once. Each time you may push several buttons simultaneously.

Assume there are 4 buttons. You can first push button 1 and button 3 at one time, then push button 2 and button 4 at one time. It can be represented as a string "13-24". Other pushing ways may be "1-2-4-3", "23-14" or "1234". Note that "23-41" is the same as "23-14".

Given the number N your task is to find all the pushing ways.

输入

An integer N. (1 <= N <= 8)

输出

Output the different pushing ways in lexicographical order.

For the same pushing way output the smallest string in lexicographical order as representative.

样例输入

3

样例输出

1-2-3
1-23
1-3-2
12-3
123
13-2
2-1-3
2-13
2-3-1
23-1
3-1-2
3-12
3-2-1

题意分析:

1.题是什么?

    给你个数字n,1<=n<=8,字典序升序输出由1到n的数字和符号'-'构成的所有字符串,要求不能重复,这个重复指的是由'-'隔开的数字集合不能重复,32和23就是重复的.

2.思路

    首先看到是按字典序输出所有字符串可能,妥妥的dfs填空,我们知道关于最简单的字符串字典序升序我们做一个flag数组记录哪些字符用过的即可,然后每层递归都由一个for循环由字典序升序逐个填入每个可用字符即可升序构造出所有不重复的字符串,

int rest;
void dfs(int nowpos){
	if(!rest){
		ans[nowpos]='\0'; 
		puts(ans);
		return;
	}
	for(int i=1;i<=n;i++){
		if(flag[i]){
			ans[nowpos]='0'+i;
			flag[i]=false;
			rest--;
			
			dfs(nowpos+1);
			
			rest++;
			flag[i]=true;
		}
	}
}

现在这个问题加深了难度,加入了一个'-'符号并且重定义了重复,认为两个字符串中每个'-'分隔开的部分都包含完全相同的字符集即视为重复

比如 12-34 与21-43也是重复的,故而我们对dfs需要做修改,一方面加入'-',一方面加入另一个标志位interrupt

'-'的规则很简单,不是第一个且前面也不是'-'则优先dfs填入,

而interrupt的设计目的是保证'-'所隔开的分块内字符为升序,interrupt存的值为当前分块内最大的字符,故而自然填入新的'-'即开始新的分块时要重置为0,填入新字符时更新interrupt,for循环也以interrupt对i做初始化;

ac代码

#include <stdio.h>
const int maxn=9;
int n;
char ans[2*maxn];
bool flag[maxn];
int rest;
int interrupt;
void dfs(int nowpos){
	if(!rest){
		ans[nowpos]='\0';//手动结尾,很重要 
		puts(ans);
		return;
	}
	if(nowpos&&ans[nowpos-1]!='-'){//不是第一个空并且前面不是'-' 
		ans[nowpos]='-';
		//修改标志 
		int temp=interrupt;
		interrupt=0;
		
		dfs(nowpos+1);
		//回溯标志 
		interrupt=temp;
	}
	for(int i=interrupt+1;i<=n;i++){
		if(flag[i]){
			ans[nowpos]='0'+i;
			
			//修改标志 
			flag[i]=false;
			rest-=1;
			int temp=interrupt;
			interrupt=i;
			
			dfs(nowpos+1);
			
			//回溯标志 
			interrupt=temp; 
			rest+=1;
			flag[i]=true;
		}
	}
}
int main(){
	scanf("%d",&n);
	rest=n;
	interrupt=0;
	for(int i=1;i<=n;i++) flag[i]=true; 
	dfs(0);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_31964727/article/details/82735619