比赛
题目
给你两个数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;
}