HDU6351 Beautiful Now【暴搜+下一个全排列】

题意:

输入两个数n,k  可以最多交换k次n各个位上的数 输出最小的组合和最大的组合

思路:

真的不想写暴搜 就当练习next_permutation函数【下一个全排列】

预处理 n最多9位数 把n的每位数都存进数组c 也可以用字符串实现

因为观察可得交换 len-1 次后 最小或者最大就不会再改变了 所以当 k>=len-1 直接输出最小和最大的组合

后面就是用神奇的next_permutation函数

这个函数有什么用呢 比如你丢一个数组a[]= {1,2,3}进去 他会自动帮你全排序

1,2,3

1,3,2

2,1,3

2,3,1

3,1,2

3,2,1

不过要注意的是 如果你丢带0的数比如109进去 他会从0开始排

在这题的话如果第一个数是0直接跳就可以了

丢一个代码大家可以去玩玩这个函数

#include <stdio.h>
#include <algorithm>
using namespace std;
int main(){
    int n;
    while(scanf("%d",&n)&&n){
        int a[1000];
        for(int i=0;i<n;i++){
            scanf("%d",&a[i]);
        }
        sort(a,a+n);//可以自行测试一下删除后的结果
        do{
            for(int i=0;i<n;i++)
                printf("%d ",a[i]);
            printf("\n");
        }while(next_permutation(a,a+n));
    }
    return 0;
}

然后真的是用特别暴力的写法了= =

就如果排序不同就遍历后面 交换

然后记录交换的次数 超过k就跳出来 不跳会超时

代码:

#include <bits/stdc++.h>

using namespace std;

int n,mklen;
int a[10];
int b[10];
int c[10];//存原来的数
int p[10], q[10];
int minn, maxx;

void solve() {
	if(c[p[1]] == 0) return;
	for(int i = 1; i <= len; i++) q[i] = p[i];
	int sum = 0,count = 0;
	for(int i = 1; i <= len; i++) {
		sum = sum*10 + c[p[i]];
		if(q[i]!=i) {
			for(int j = i+1; j <= len; j++) {
				if(q[j] == i) {
					swap(q[j],q[i]);
					count++;
					if(count > m) return;
					break;
				}
			}
		}
	}
	if(count <= m) {
		minn = min(sum,minn);
		maxx = max(sum,maxx);
	} else return;
}

int main() {
	int t;
	scanf("%d",&t);
	while(t--) {
		scanf("%d%d",&n,&k);
		memset(a,0,sizeof(a));
		memset(b,0,sizeof(b));
		memset(c,0,sizeof(c));
		len = 0;
		while(n) {
			a[n%10]++;
			b[n%10]++;
			c[len+1] = n%10;
			n /= 10;
			len++;
		}

		//因为刚才数组是倒着存的 所以我们操作一下把他倒回来
		//比如输入12345 c[]={5,4,3,2,1} 所以我们要把他倒回12345
		for(int i = 1; i <= len/2; i++) {
			swap(c[i],c[len+1-i]);
		}

		//如果k>=len-1 直接输出最小最大 最小要从非0开始
		if(k >= len - 1) {

			for(int i = 1; i <= 9; i++) {
				if(a[i]) {
					printf("%d",i);
					a[i]--;
					break;
				}
			}
			for(int i = 0; i <= 9; i++) {
				while(a[i]) {
					printf("%d",i);
					a[i]--;
				}
			}
			printf(" ");

			for(int i = 9; i >= 0; i--) {
				while(b[i]) {
					printf("%d",i);
					b[i]--;
				}
			}
			printf("\n");
			continue;
		}

		minn = 999999999, maxx = -1;
		for(int i = 1; i <= len; i++) p[i] = i;
		do {
			solve();
		} while(next_permutation(p+1,p+1+len));

		printf("%d %d\n",minn,maxx);
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值