codeforces 915C Permute Digits (枚举)

https://blog.csdn.net/zuzhiang/article/details/79076522

传送门:Permute Digits

 

题目大意:

给你两个数 a和 b,可以打乱 a每位数的顺序,让你求满足 <=b 的最大值。保证结果一定存在。

 

思路:

由于结果一定存在,只有 b 的位数大于或等于 a 两种情况,如果 b 的位数大于 a 时,将 a 的每位数按从小到大的顺序输出即可。 当两者位数相等时,我们要尽可能保证结果的高位和 b的相应位相等,一旦出现结果的某一位小于 b,则将没用到的数按从小到大输出即可。

但是这样会出现一个问题,例如: a=1234   b=1230,当确认好前 3位为 123时,第 4位是不满足条件的,这时候要在回溯的过程中解决。

 

一点思考:

DFS其实就是用递归的方法按照一定顺序枚举所有可能的结果,所谓的回溯就是当当前路径不满足条件时,走别的路径看看是否满足条件,当满足条件时则退出,终止所有的递归。由于是按贪心的思维枚举的,所以比一般的暴力枚举的时间复杂度要低很多。

其实枚举一个小于的位就可以了。。。从低位向高位枚举。。。默认枚举的位i之前的位a和b都相同,第i位a小于b,后面取最大就行了,O(18^3)

#include<bits/stdc++.h>
#define rep(i, j, k) for (int i=j; i<k; i++)
#define ll long long
#define dprintf if (debug) printf
using namespace std;
int val(char s){
	return s - '0';
}
char x[100],y[100], ans[100];
const int debug = 1;
int vis[100];
int lenx, leny;
int flag;
int main(){
	scanf("%s", x);
	scanf("%s", y);
	lenx = strlen(x);
	leny = strlen(y);
	//dprintf("x = %s\n", x);
	sort(x, x+lenx);
	if (lenx < leny){
		for (int i=lenx-1; i>=0; i--){
			printf("%c", x[i]);
		}
		return 0;
	}
	for (int i=lenx; i>=0; i--){///?????????????keyijia1??
		//di wei xiao
		memset(vis, 0, sizeof(vis));
		flag = true;
		for (int j=0; j<i; j++){
			int find = 0;
			for (int k=0; k<lenx; k++){
				if (x[k] == y[j] && !vis[k]){
					vis[k] = 1;
					ans[j] = x[k];
					find = 1;
					break;
				}
			}
			if (!find) {
				flag = false;
				break;
			}
		}
		if (!flag) continue;
		if (i < lenx){
			flag = false;
			for (int j=lenx-1; j>=0; j--){
				if (x[j]<y[i] && !vis[j]){
					vis[j] = 1;
					flag = true;
					ans[i] = x[j];
					break;
				}
			}
			if (!flag) continue;
		}
		for (int j=i+1; j<lenx; j++){
			for (int k=lenx-1; k>=0; k--){
				if (!vis[k]){
					vis[k] = 1;
					ans[j] = x[k];
					break;
				}
			}
		}
		//dprintf("i = %d\n", i);
		printf("%s", ans);
		return 0;
	}
	return 0;
}

 注意一下char[] 字符串数组可以使用< 哦

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值