您的位置:首页 > 其它

hdu-3183A Magic Lamp(贪心)

2015-11-17 16:12 471 查看


题目的意思是:

给你一个大数,然后删减其中的K个数,并且剩下的数还是按原来在的先后次序排列,求所得的那个数最小的那个数。

思路:贪心(要取得数最小,你从左往右选数的时候,选的第一数,就是选后组成数的位权最高的,要一个数最小,位权最高的所对应那位要最小,然后依次是下一位权最小)。原来有N个数,删除K个数得最小数可以转化为从左往右选N-K个数所组成的数最小。那么第一个数必须在区间[0,K](数组下标)(存大数的数组首位是从0开始的)。

证:选的第一位数如果超过K,假如取的是K+S(K+S<=N-1)那么从(K+S+1)到N-1还剩下(N-K-S-1)个数,因为已经选了一个数剩余(N-K-1)个数没选,那么这些数必定要在区间

[K-S+1,N]上选。又(N-K-1)大于区间长度N-K-S-1(S>=1).

所以第一个数只能在[0,K]上取,且要取最小值,每位取当前区间最小才能保证最后所得数最小。

那么当第一个数取完后,取的是pos位置的,那么在[0,pos-1]是未取得数,也就是去掉的数,因为后面省下的(N-K-1)个数不能在这些位置去,因为这些数在pos之前,所以如果去的话

在所得的数中位置在第一个数之前,所以与pos为第一个数矛盾。

这样你选第二个数时此时K应该更新为K-(pos+1-n)(n为当前所选好的数的个数(当前n=1)),pos更新为pos+1;那么第二个数在区间[pos,pos+K]其实pos+K就为K+n;

那么这样直到选好N-K个数就行了。

/*RMQ优化 复杂度为n*log(n)*/
1 #include<stdio.h>
#include<algorithm>
#include<iostream>
#include<stdlib.h>
#include<string.h>
#include<math.h>
void RMQup(int k,int l);
int que(int i,int j);
int Min(int x,int y);
char a[2000];
int  b[2000];
const int N=100;
int RMQ[1005][1005];
using namespace std;
int main(void)
{
int n,i,j,k,p,q,l,m;
while(scanf("%s",a)!=EOF)
{
scanf("%d",&k);
l=strlen(a);
p=l-k;
for(i=0; i<l; i++)
RMQ[0][i]=i;
int r=log2(l);
r++;
RMQup(r,l);
int pp,qq;
int dd;
pp=0;
m=k;
int coutt =0;
while(coutt<p)//选好p个数字就结束
{
int z=que(pp,m);
b[coutt++]=a[z]-'0';
pp=z+1;
m++;
}
for(i=0; i<p; i++)
{
if(b[i]!=0)
{
break;
}
}
for(j=i; j<p; j++)
{
printf("%d",b[j]);
}
if(i==p)
{
printf("0");
}
printf("\n");
}

return 0;

}

void RMQup(int k,int l)//dp求RMQ(这种RMQ链接讲解http://www.cnblogs.com/zzuli2sjy/p/4971449.html)
{
int i,j;
for(i=1; i<=k; i++)
for(j=0; j<l; j++)
if(j+(1<<i-1)<l)
RMQ[i][j]=Min(RMQ[i-1][j],RMQ[i-1][j+(1<<i-1)]);

}

int que(int i,int j)
{
int f=log2(j-i+1);
return Min(RMQ[f][i],RMQ[f][j-(1<<f)+1]);

}
int Min(int x,int y)//求在某段的最小值的数组下标
{
if(a[x]==a[y])
{
return x<y?x:y;//当两个数相同时返回数组下标小的(比如223 要去1个数字,答案是22,如果返回数组下标大的结果就是23了)
}
else
{
return a[x]<a[y]?x:y;
}
}


/*直接循环找段最小*/
#include<stdio.h>
#include<algorithm>
#include<iostream>
#include<stdlib.h>
#include<string.h>
using namespace std;
char a[1005];
char b[1005];
int main(void)
{
int n,i,j,k,p,q,l;
while(scanf("%s",a)!=EOF)
{
scanf("%d",&k);
l=strlen(a);
if(k==l)
{
printf("0\n");
}
else
{
int y=l-k;
int x=0;
int m=y;
int coutt=0;
int dd;
dd=0;
while(coutt<y)
{
b[coutt]=a[x];
for(i=x; i<=x+k; i++)//循环找最小
{
if(a[i]<b[coutt])
{
b[coutt]=a[i];
dd=i;
}

}
dd=dd+1;
k-=(dd-x-1);
coutt++;
x=dd;
}
for(i=0; i<coutt; i++)
{
if(b[i]!='0')
{
break;
}
}
if(i==coutt)
{
printf("0");
}
for(j=i; j<coutt; j++)
{
printf("%c",b[j]);
}
printf("\n");
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: