UPC-吉利数字

UPC-吉利数字

题目描述

Farmer John马上就要过生日了,奶牛们想给他送一份礼物。由于预算不足,奶牛们打算把对Farmer John的爱寄托在一个数字中。奶牛们知道Farmer John认为的吉利的数字有m(1 ≤ m ≤ 10) 个,也就是阿拉伯数字0到9这十个数的一个子集。如果一个正数没有前导零,且其中的每一位都是Farmer John认为的吉利的数字,那么这个数就是一个吉利数。
考虑到Farmer John生日那天是农场建立的第n天,奶牛们希望用这m个数生成一个不超过n且最接近n的一个吉利数,把它送给Farmer John。奶牛们没想到n实在太大了,所以她们请你帮忙计算一下这个礼物是多少。

输入

输入包含两行,第一行包含两个整数n和m
第二行包含m个整数,每个数都是0到9中的一个。数据保证这m个整数互不相同

输出

仅一行,即不超过n的最大的吉利数
如果无解,请输出-1

Sample Input

2019 2
1 9

Sample Output

1999

这题的最初来源是海淀区第三届智慧杯编程思维类复赛(C++)

原题解用贪压和递归,咱也没整明白。所以还是自己做了

UPC-吉利数字_第1张图片

听说我写的博客让你们非常的迷茫,所以这一次更新我好好解释以下我的内容吧………………
首先献上自己的贪心加模拟的垃圾代码(我要看题解)

#include
using namespace std;
typedef long long ll;
char u[100005],save[11],ans[100005];
bool cmp(char a,char b) {
 return a>b;
}
int main() {
 int num;
 cin>>u;
 cin>>num;
 for(int i=0; i<num; i++)
  cin>>save[i];
 sort(save,save+num,cmp);
 int l=strlen(u);
 if(num==1&&save[0]=='0') {
  cout<<"-1"<<endl;
  return 0;
 }
 int i;
 for(i=0; i<l; i++)
  ans[i]=save[0];
 for(i=0; i<l; i++) {
  if(ans[i]==u[i])
   continue;
  if(ans[i]<u[i]) {
   int j=0;
   if(ans[j]=='0')
    j++;
    if(j>=l)
    {
        cout<<"-1"<<endl;
        return 0;
    }
   for(; j<=i; j++)
    putchar(ans[j]);
   for(int j=i+1; j<l; j++)
    putchar(save[0]);
   cout<<endl;
   return 0;
  }
  int temp=0;
  while(ans[i]>u[i]) {
   if(temp>num-1)
    goto A;
   ans[i]=save[temp++];
  }
  i--;
 }
 cout<<ans<<endl;
 return 0;
A:
 for(int j=i-1; j>=-1; j--) {
  if(j==-1) {
   l--;
   if(!l) {
    cout<<-1<<endl;
    return 0;
   }
   for(i=0; i<l; i++)
    putchar(save[0]);
   putchar('\n');
   return 0;
  }
  if(ans[j]==save[num-1])
   continue;
  if(ans[j]!=save[num-1]) {
   for(int k=0; k<num; k++)
    if(ans[j]==save[k]) {
     ans[j]=save[k+1];
     for(int z=0; z<=j; z++)
      putchar(ans[z]);
     for(int z=j+1; z<l; z++)
      putchar(save[0]);
     putchar('\n');
     return 0;
    }
  }
 }
}


OK,思路就是贪心,自己拿个笔戳一戳也能看出来门道。
下面按照种花家的亲们的要求,来做一下解释
首先整体思路如下:
1、先填入如果可以的最大值(不是真的最大值,只是最理想的最大值)
PS:接下来的这个数和原来的数的含义是指每一位对应的数字.
2、从前往后,如果有一位数是比原来的数小的话,那么从这个数之后的所有数字都是最大值
3、如果一个数比原来的数大,那么就让他降到所有的可填充数中最大的且不大于原来数字的数字。如果都无法实现,那么就往前面找,是否有一个数字不是填充数字中最小的。(因为如果不是最小的可填充数就可以让这个填充数往下减少)如果都是,那么位数减少一,剩下的全部以可填充数字最大值输出。
4、特殊考虑如果位数只有一个,而且可能出现前导0的情况!
然后思路有了,接下来就是纯模拟了。模拟起来有点复杂,所以一定要捋清思路,不要迷茫!

By-轮月

你可能感兴趣的:(ACM,中国石油大学OJ)