#贪心#SSL 2574 Closest

本文解析了一道关于数字操作的比赛题目,通过贪心算法找出由给定数字B打乱形成的两个新数,其中一个要小于等于给定数A且尽可能大,另一个要大于等于A且尽可能小。文中提供了详细的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

比赛

题目

给你两个数A,B,把B打乱后形成两个数字相同位置不同的数。
一个小于A的数并且是这些数当中最大的和一个大于等于A的数并且是这些数中最小的(不能有前导0)


分析

贪心,具体详见代码


代码

#include <cstdio>
#include <cstring>
#include <cctype>
#include <algorithm>
using namespace std;
char s1[62],s2[62],s3[62],s4[62]; 
int len1,len2,len3,len4,x;
bool v1[62],v2[62],flag1;
int zxd(bool *v,char x){
	for (int i=1;i<=len2;i++) if (s2[i]==x&&!v[i]) return i;
	return -1;
}
char zbx(bool *v,char x){
	char c='/'; int k=-1;
	for (int i=1;i<=len2;i++) if (s2[i]>c&&s2[i]<x&&!v[i]) k=i,c=s2[i];
	v[k]=1; return c;
}
char zbd(bool *v,char x){
	char c=':'; int k=-1;
	for (int i=1;i<=len2;i++) if (s2[i]<c&&s2[i]>x&&!v[i]) k=i,c=s2[i];
	v[k]=1; return c;
}
int digit(char *s,int len){for (int i=1;i<=len;i++) if (!isdigit(s[i])) return i; return 0;}
int main(){
	gets(s1+1); gets(s2+1);
	len1=strlen(s1+1); len2=strlen(s2+1);
	for (int i=1;i<=len1;i++){
		int g=zxd(v1,s1[i]);//找相同的位置
		if (flag1) s3[++len3]=zbd(v1,'/');//如果前面只找到小的,那么后面都只用找大的
		else if (g!=-1) s3[++len3]=s2[g],v1[g]=1;//相同的(逼近)
		else flag1=1,s3[++len3]=zbd(v1,s1[i]);//只找到大的
	}
	if (x=digit(s3,len3)){//特判,存在(:Ascil 58)
		int i;
		for (i=1;i<=len2&&v1[i];i++);
		s3[x]=s2[i];//找到:的地方
		for (i=len3;i>1;i--){//修改
		int j=0;
		for (j=i-1;j>=1&&s3[i]<=s3[j];j--);
		if (!j) continue; swap(s3[i],s3[j]);
		for (int t1=j+1;t1<len3;t1++)
		for (int t2=t1+1;t2<=len3;t2++)
		if (s3[t1]>s3[t2]) swap(s3[t1],s3[t2]);
		break;
	    }
	}
	if (isdigit(s3[1])&&strcmp(s1+1,s3+1)<=0) puts(s3+1); else putchar('0'),putchar('\n');//第一个是:说明是无解的,修改后完不成也是无解的
	flag1=0; for (int i=1;i<=len1;i++){
		int g=zxd(v2,s1[i]);
	if (flag1) s4[++len4]=zbx(v2,':');//如果前面只找到大的,那么后面都只用找小的
		else if (g!=-1) s4[++len4]=s2[g],v2[g]=1;//相同的(逼近)
		else flag1=1,s4[++len4]=zbx(v2,s1[i]);//只找到小的
	}
	if (strstr(s1+1,s4+1))//相同
	for (int i=len4;i>1;i--){//修改
		int j=0;
		for (j=i-1;j>=1&&s4[i]>=s4[j];j--);
		if (!j) continue; swap(s4[i],s4[j]);
		for (int t1=j+1;t1<len4;t1++)
		for (int t2=t1+1;t2<=len4;t2++)
		if (s4[t1]<s4[t2]) swap(s4[t1],s4[t2]);
		break;
	}
	if (isdigit(s4[1])) puts(s4+1); else putchar('0'),putchar('\n');//第一个是/说明无解
	return 0;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值