【思路、优化】UVa 11491 - Erasing and Winning

Juliano is a fan of the TV show Erasing and Winning, where participants are selected in a draw and receive money for taking part in the show.

In the show, the presenter writes a number of N digits in a board. The participant must then erase exactly D digits from the number in the board; the number formed by the remaining digits is the value of the money prize for the participant.

Juliano was at last selected to take part in the show, and asked you to write a program that, given the number the presenter wrote in the board, and the number of digits Juliano must erase, determines the highest value of the prize he can win.

Input

The input contains several test cases. The first line of a test case contains two integers N and D (1 ≤ D < N ≤ 105 ) indicating respectively the number of digits of the number the presenter wrote in the board and the number of digits that must be erased. The next line contains the number the presenter wrote; the number does not start with a zero. The end of input is indicated by a line containing only two zeros, separated by a space.

Output

For each test case in the input your program must produce one single line in the output, containing the highest prize Juliano can win.

Sample Input

4 2

3759

6 3

123123

7 4

1000000

0 0

Sample Output

79

323

100

题意:题目很好理解,给你一串数,要求消去其中的D个数,使剩下的数最大。

分析:TLE了很长时间一直优化不成功。后来才知道思路就很暴力。下面给两个思路,可以都尝试一下;

①首先记录每个数字0~9出现的位置,然后从9~0开始循环,从后往前依次将数字放到相应位置,期间注意一旦放置(N-D)个数字后立即退出循环。最后扫一遍字符串,没有数字的位置不输出。这样复杂度为0(n*10);

②第二个思路是网上的思路,先从头扫描,一旦发现digit[i]<digit[j]&&(i<j),就从i处向前将小于digit[j]的数删掉;

首先看了思路之后自己尝试写了一下,可惜优化的还是不好(读者也可以先根据思路尝试写下,独立AC更有成就感吖~)。

后来看了题解,发现可以用list实现,list的erase与iter的灵活运用很有用处。

下附代码

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 #include<cstring>
 5 #include<list>
 6 using namespace std;
 7 int d, n, alnum[12];
 8 char num[100010];
 9
10 void solve()
11 {
12     list<int> ans;
13     ans.push_back(10);
14     for(int i = 0; i < n; i++)
15     {
16         ans.push_back(num[i]-‘0‘);
17     }
18     ans.push_back(10);
19
20     list<int>::iterator head, tail, iter;
21     head = ans.begin(); head++;
22     tail = ans.begin();
23     int cnt = 0;
24     while(cnt < d)
25     {
26         if(*head > *tail)
27         {
28             ans.erase(tail);
29             head--;
30             tail = head;
31             head++;
32
33             cnt++;
34         }
35         else
36         {
37             head++;
38             tail++;
39         }
40     }
41     ans.pop_back();
42     for(iter = ans.begin(); iter != ans.end(); iter++)
43     {
44         if(*iter == 10) continue;
45         printf("%d", *iter);
46     }
47     printf("\n");
48 }
49
50 int main()
51 {
52     //freopen("in.txt", "r", stdin);
53     while(scanf("%d%d", &n, &d))
54     {
55         if(!n && !d) break;
56         scanf("%s", num);
57         solve();
58     }
59     return 0;
60 }

时间: 2025-01-11 09:22:57

【思路、优化】UVa 11491 - Erasing and Winning的相关文章

uva 11491:Erasing and Winning(贪心)

题意:给一个长n(n<10^5)位的数,删除d位,求删除后最大的数.(原数无前导0) 思路:从前往后扫,如果a[i] > a[i-1],则删除a[i-1].我暴力的用链表实现了…… #include <cstdio> #include <cstring> #include <cstdlib> #include <list> using namespace std; #define N 100020 char str[N]; int main()

UVA 11491 Erasing and Winning

#include<bits/stdc++.h> #define REP(i,a,b) for(int i=a;i<=b;i++) #define MS0(a) memset(a,0,sizeof(a)) #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 using namespace std; typedef long long ll; const int maxn=1000100; const int INF=1

UVA 11491 Erasing and Winning 奖品的价值 (贪心)

题意:给你一个n位整数,让你删掉d个数字,剩下的数字要尽量大. 题解:因为最后数字位数是确定的,而且低位数字对答案的贡献是一定不及高位数字的,所以优先选择选最大且最靠左边的数字,但是有一个限制,选完这个数字以后右边剩下的数字要保证足够接下来的选择,所以我想到了优先队列,记录一个信息,选的数字所在的位置,以及上一个数字所在的位置,如果当前出队的数字在上一个选的位置前面就直接丢掉,每次选完一个以后剩下要选的数字就减少了,满足限制的条件的数字会增加,再把新的待选数字加入队列. #include<bit

UVa 11491 Erasing and Winning 题解

难度:α 用时:30 min 题目:?? 这是个裸贪心题. 题目要求在某数字字符串中删去给定个数的字符,使剩下来的数字最大. 那么不难想到用队列.线性复杂度.0 ms. 每读入一个数,就把之前比较小的拿掉. 注意不能拿太多,否则长度不够. 队满了也不能继续放.(除非有更大的元素可以把队尾的怼下去) 1 for (int i = 0; i < d; i++) { 2 char c = getchar(); 3 while (it > 0 && ans[it] < c &am

11491 - Erasing and Winning(贪心)

一开始真的没想到这竟然是一道贪心题目.  不过后来仔细想想也就明白了. 我采取的做法是自前向后扫一遍,用一个指针rear动态维护答案数组中的最后一个元素,如果遇到一个比它大的数s[i],那么从它开始将它及其它之前的比s[i]小的数全部删除,并且用变量cnt记录删除的个数, 防止删除多了. 对于贪心算法的正确性我们不难用反证法来证明: 假设这样做不是最优的,那么如果不这样做,对于一个长度一定的答案,得到的结果一定小于这样做的结果. 但是还有可能少删了,也就是第三组样例那种情况,所以我们贪心结束后要

UVa 11491 奖品的价值

https://vjudge.net/problem/UVA-11491 题意:一个n位整数,删除其中的d个数字,输出最大值. 思路:肯定从高位开始分析,代码如下. 1 #include<string> 2 #include<iostream> 3 using namespace std; 4 5 const int maxn = 100000 + 5; 6 7 int n, d; 8 char a[maxn]; 9 10 int main() 11 { 12 //freopen(

uva11491 Erasing and Winning

边读入边处理 优化了速度一开始有想错了的地方.处理输入有点想用stringstream, 的问题在于他把字符串连续的数字作为一个整体,遇到空格才分开,所以不适用 #include<cstdio> #include<cstdlib> #include<iostream> #include<sstream> #include<cstring> using namespace std; const int maxn = 100005; int s[ma

UVA-11491 Erasing and Winning (单调队列)

题目大意:给一个数字(开头非0),拿掉其中的d个数字,使剩下的数字最大(前后顺序不能变). 题目分析:拿掉d个数字,还剩下n-d个数字.相当于从n个数字中按先后顺序选出n-d个数字使组成的数字最大,当然采用窗口滑动优先选取大的. 代码如下: # include<iostream> # include<cstdio> # include<cstring> # include<algorithm> using namespace std; struct Num

redis在实践中的一些常见问题以及优化思路

1.fork耗时导致高并发请求延时 RDB和AOF的时候,其实会有生成RDB快照,AOF rewrite,耗费磁盘IO的过程,主进程fork子进程 fork的时候,子进程是需要拷贝父进程的空间内存页表的,也是会耗费一定的时间的 一般来说,如果父进程内存有1个G的数据,那么fork可能会耗费在20ms左右,如果是10G~30G,那么就会耗费20 * 10,甚至20 * 30,也就是几百毫秒的时间 info stats中的latest_fork_usec,可以看到最近一次form的时长 redis单