您的位置:首页 > 其它

HDU3183 RMQ/贪心

2015-11-07 14:31 295 查看

A Magic Lamp

[align=left]Problem Description[/align]
Kiki likes traveling. One day she finds a magic lamp, unfortunately the genie in the lamp is not so kind. Kiki must answer a question, and then the genie will realize one of her dreams.
The question is: give you an integer, you are allowed to delete exactly m digits. The left digits will form a new integer. You should make it minimum.
You are not allowed to change the order of the digits. Now can you help Kiki to realize her dream?

[align=left]Input[/align]
There are several test cases.
Each test case will contain an integer you are given (which may at most contains 1000 digits.) and the integer m (if the integer contains n digits, m will not bigger then n). The given integer will not contain leading zero.

[align=left]Output[/align]
For each case, output the minimum result you can get in one line.
If the result contains leading zero, ignore it.

[align=left]Sample Input[/align]

178543 4
1000001 1
100001 2
12345 2
54321 2

[align=left]Sample Output[/align]

13
1
0
123
321

[align=left]题意:给出一个不超过1000位的字符串,求删去m个数字以后可以形成的最小的数是多少。[/align]
[align=left]题解:[/align]
贪心:
首先考虑对于n个数字组成的数,只删除1位的情况。

比如176832,删除一位使得剩下的数值最小。结果是删除7而不是删除8所以可知并不总是删除最大的那个数字。

一种可行的贪心策略是:对于n位数构成的数删除m位,每次总是删除这样的a[i]:它是第一个a[i]>a[i+1]的数,如果不存在则就删除a
如何证明给贪心策略是正确的呢?

假设始终不删除a[i],那么最终m位数就必然包含a[i]。但其实a[i]>a[i+1],所以我们完全可以删除a[i],然后让a[i+1]在a[i]最终的位置上,那么得到的m位数自然更小了。所以a[i]必定要被删除的。以此类推,贪心得证。

RMQ:

因为要找n-m个数,删除m个数。所以原数的第1位到m+1位的数字中最小的那位(假设是第i位)肯定是n-m位数的第一位。(想想为什么)

这样我们就找到了第一位a[i],接下来我们在从第i+1位数到m+2位数中找最小的那位,这个肯定是n-m位数的第二位。

以此类推,找够n-m位即可。

RMQ函数要做点修改。dmin[i][j]=k表示的是区间[i,i+(1<<j)-1]内最小值的下标而不是值了。

///1085422276
#include<bits/stdc++.h>
using namespace std ;
typedef long long ll;
#define mem(a) memset(a,0,sizeof(a))
inline ll read()
{
ll x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9')
{
if(ch=='-')f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
//****************************************
#define maxn 1999+5
#define mod 1000000007
int dp[maxn][200],k,len;
char a[maxn];
int Min(int x,int y){
return a[x]<=a[y]?x:y;
}
void RMQ_init(){
mem(dp);
for(int i=0;i<len;i++){
dp[i][0]=i;
}
for(int i=1;(1<<i)<len;i++){
for(int j=0;(j+(1<<i)-1)<len;j++){
dp[j][i]=Min(dp[j][i-1],dp[j+(1<<(i-1))][i-1]);
}
}
}
int Q_RMQ(int l,int r){
int kk=(int)(log((double)(r-l+1))/log(2.0));
return Min(dp[l][kk],dp[r-(1<<kk)+1][kk]);
}vector<int >ans;
int main(){
while(scanf("%s%d",a,&k)!=EOF){
len=strlen(a);ans.clear();
RMQ_init();//cout<<1<<endl;
k=len-k;int pos=0;
while(k--){
pos=Q_RMQ(pos,len-k-1);
ans.push_back(pos);
pos=pos+1;
}bool bo=0;bool flag=0;
for(int i=0;i<ans.size();i++){
if(flag){
cout<<a[ans[i]];bo=1;flag=1;
}
else  if(a[ans[i]]!='0'){flag=1;cout<<a[ans[i]];bo=1;}
}if(!bo)cout<<0<<endl;
else
cout<<endl;
}
return 0;
}


代码
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: