删数问题

今天学了学优先队列,做了做P1323删数问题,但首先调了调P1106删数问题的代码(前几天WA了)。

先看P1106:

洛谷P1106 删数问题

题目描述

键盘输入一个高精度的正整数 N(不超过 250 位),去掉其中任意 k 个数字后剩下的数字按原左右次序将组成一个新的非负整数。编程对给定的 N 和 k,寻找一种方案使得剩下的数字组成的新数最小。

输入格式

n(高精度的正整数 )。

k(需要删除的数字个数 )。

输出格式

最后剩下的最小数。

输入输出样例

输入 #1
175438 
4
输出 #1
13
 这道题的思路不难,就是简单的贪心,如果一位数比它右边的这位数大,就删掉它,但有一个问题,如果本来一位数比它右边的这位数小,但到下一位时却将右边这位删掉了,使得这位数右边的这位换了一个数,而且要是换得小了,那么就要再将这位数删了,所以在每次删数时都要往前找。
主要思路就是这些,但是还有几个小小的问题——
1.答案中的前导零的问题:删数后应该不难出现0前的数都删了,会出现前导零,如:100010删一个数后是00010,但要去除前导零,就是10。
int p=0;
for(int i=1;i<=n;i++){
    if(shu[i]!=-1&&(shu[i]!=0||p==1)){
        p=1;
        cout<<shu[i];
    }
}
if(p==0) cout<<0;

2.我删数的时候是将这位数改为-1,可是如果碰到-1,向前找的也会停止,那就要将-1无视掉,直接往前找,只有找到比它小的数才会停。

if(shu[i]>shu[i+1]){
    shu[i]=-1;
    k--;
    int t=i;
    while(t>1&&shu[i+1]<shu[t-1]&&k>0){
        shu[t-1]=-1;
        t--;
        k--;
    }
}

下面是这道题完整的代码:

#include<iostream>
#include<cstring>
using namespace std;
int main(){
    char a[255];
    scanf("%s",a);
    int n=strlen(a);
    int shu[255];
    for(int i=1;i<=n;i++){
        shu[i]=a[i-1]-'0';
    }
    int k;
    cin>>k;
    for(int i=1;i<=n;i++){
        if(k==0){
            break;
        }
        if(shu[i]>shu[i+1]){
            shu[i]=-1;
            k--;
            int t=i;
            while(t>1&&shu[i+1]<shu[t-1]&&k>0){
                shu[t-1]=-1;
                t--;
                k--;
            }
        }
    }
    int p=0;
    for(int i=1;i<=n;i++){
        if(shu[i]!=-1&&(shu[i]!=0||p==1)){
            p=1;
            cout<<shu[i];
        }
    }
    if(p==0) cout<<0;
    return 0;
}

洛谷P1323 删数问题

题目描述

一个集合有如下元素:1 是集合元素;若 P 是集合的元素,则 2×P+1,4×P+5 也是集合的元素。

取出此集合中最小的 k 个元素,按从小到大的顺序组合成一个多位数,现要求从中删除 m 个数位上的数字,使得剩下的数字最大,编程输出删除前和删除后的多位数字。

注:不存在所有数被删除的情况。

输入格式

只有一行两个整数,分别代表 k 和 m。

输出格式

输出为两行两个整数,第一行为删除前的数字,第二行为删除后的数字。

输入输出样例

输入 #1
5 4
输出 #1
137915
95
说明/提示

数据规模与约定

  • 对于 30% 的数据,保证 1k,m300。
  • 对于 100% 的数据,保证 1k,m3×10^4。

优先队列的部分很少,优先队列就是STL中的一个队列,默认为小跟堆,加进去后直接自动排列为小跟堆。

头文件:

#include<queue>

优先队列定义:

priority_queue<ll,vector<ll>,greater<ll> > ji;//ll为long long。

加入元素:

ji.push(i);

取出头元素:

i=ji.top();

删除头元素:

ji.pop();

然后说一下这道题的思路,这个集合就是{P,2*P+1,4*P+3,4*P+5,……}(P=1),其中P的系数是4n的数就是P的系数是2n的数*2+1和P的系数是n的数*4+5,以此类推,这样就是一个斐波那契数列,但是这样就有一个问题,优先队列中只能取到队列中最小的数,想要处理下一个数就需要将头元素删掉,那么我们就不能将P的系数为2n的数和为n的数运算得到P的系数是4n的数,而是要将P的系数为n的数处理成为P的系数为2n得数和为4n的数,并随着输出(我这里是先存下来——为删数而存,再在结束后输出)。

int x=0,y=1;
while(k>0){
    for(int i=1;i<=min(x,k);i++){
        ll t=ji.top();
        ji.pop();
        ji.push(t*2+1);
        ji.push(t*4+5);
        int cnt=a[0]+1;
        while(t>0){
            a[++a[0]]=t%10;
            t=t/10;
        }
        int j=a[0];
        while(cnt<j){
            swap(a[cnt],a[j]);
            cnt++;
            j--;
        }
    }
    k-=min(x,k);
    int t=x;
    x=y;
    y+=t;
}

下面是整个的代码:

#include<iostream>
#include<queue>
#define ll long long
using namespace std;
priority_queue<ll,vector<ll>,greater<ll> > ji;
int a[300010];
int main(){
    int k,m;
    cin>>k>>m;
    ji.push(1);
    int x=0,y=1;
    while(k>0){
        for(int i=1;i<=min(x,k);i++){
            ll t=ji.top();
            ji.pop();
            ji.push(t*2+1);
            ji.push(t*4+5);
            int cnt=a[0]+1;
            while(t>0){
                a[++a[0]]=t%10;
                t=t/10;
            }
            int j=a[0];
            while(cnt<j){
                swap(a[cnt],a[j]);
                cnt++;
                j--;
            }
        }
        k-=min(x,k);
        int t=x;
        x=y;
        y+=t;
    }
    for(int i=1;i<=a[0];i++){
        cout<<a[i];
    }
    cout<<endl;
    for(int i=1;i<=a[0];i++){
        if(m==0){
            break;
        }
        if(a[i]<a[i+1]){
            a[i]=-1;
            m--;
            int t=i;
            while(t>1&&(a[i+1]>a[t-1]||a[t-1]==-1)&&m>0){
                if(a[t-1]!=-1) m--;
                a[t-1]=-1;
                t--;
            }
        }
    }
    int p=0;
    for(int i=1;i<=a[0];i++){
        if(a[i]!=-1&&(a[i]!=0||p==1)){
            p=1;
            cout<<a[i];
        }
    }
    if(p==0) cout<<0;
    return 0;
}

 

posted @ 2022-02-28 19:32  zzzzzz2  阅读(235)  评论(0编辑  收藏  举报