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; }
相关文章推荐
- Activity和Service绑定
- 深度学习模型之各种caffe版本(Linux和windows)的网址和配置
- TableView编辑中实现多行删除方法以及注意
- 用rabbitMQ实现生产者消费者
- 【黑马程序员】C语言运算符
- sql2008 启动报错:应用程序的组件中发生了无法处理的异常和值不能为空 viewinfo(已解决!)
- 机器视觉之 ICP算法和RANSAC算法
- 产品思路
- 老码农教你学英语
- 图片压缩成指定大小
- 数据库事务介绍
- Sharepoint中出现webpart部署之后却找不到的一种情况
- Jquery操作Cookie
- Windows Server 2008 R2(x64) IIS7+PHP5(FastCGI)环境搭建
- 常用的监测系统状态shell脚本
- 2015年rctf web150 (Update set 二次注入)
- Android数据库更新并保留原来数据的实现
- dialog.setCancelable与setCanceledOnTouchOutside的区别
- Codeforces Round #331 (Div. 2) B. Wilbur and Array
- 【Leet Code】34. Search for a Ranged---Medium