每日一题之 hiho220周 Push Button I

描述
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的全排列中间插入“-”号,输出所有不同的串。

###思路:
本题的数据范围只有N <= 8,又要求输出所有的解。比较容易想到就是穷举/暴搜。
不过我们仍应该先估计一下解的数量的上界。考虑每种表示法都是一个1~N的排列中插入若干个减号,所以解的数量不超过N! * 2^(N-1)。当N=8时大约是5000000,可以接受
具体dfs的方法是首先枚举以每个数开头的情况,所有情况枚举完之后考虑将“-”号用数字覆盖掉。

#include <bits/stdc++.h>

using namespace std;

const int maxn = 128;

bool vis[maxn];
char ans[maxn] = "-";

void dfs(int ptr, int cnt,int n)
{
	if (cnt == 0) {
		for (int i = 1; i < ptr; ++i)
			cout << ans[i];
		cout << endl;
		return;
	}
	if (ans[ptr-1] == '-') { //枚举以每个数字开头的情况
		for (int i = 1; i <= n; ++i) {
			if (vis[i]) continue;
			vis[i] = true;
			ans[ptr] = i+'0';
			dfs(ptr+1,cnt-1,n);
			vis[i] = false; //回溯
		}
		return;
	}
	ans[ptr] = '-'; //前一个位置已经是数字了,那么当前位置可以放“-”
	dfs(ptr+1,cnt,n);
	for (int i = ans[ptr-1]-'0'+1; i <= n; ++i) { //用比前一个位置大的数把“-”覆盖
		if (vis[i]) continue;
		vis[i] = true;
		ans[ptr] = i+'0';
		dfs(ptr+1,cnt-1,n);
		vis[i] = false; // 回溯
	}
}


int main()
{
	int n;
	cin >> n;
	dfs(1,n,n);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值