BZOJ 4029 HEOI2015 定价 数位贪心

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=4029

题意概述:
对于一个数字的荒谬程度定义如下:删除其所有的后缀0,然后得到的数字长度为a,如果最后一个数字是5,荒谬程度为2*a-1,否则荒谬程度为2*a
现给出一些区间[L,R],询问区间内荒谬程度最小的价格。如果有多个,给出最低的那个。

T<=100,1<=L,R<=10^9

 

分析:

本来以为找到了一个数位dp的题结果发现随意分析一下性质就成了个贪心。。。。

首先可以发现最后一位是非0的情况都可以O(1)求解,需要注意的只有是0的情况,而且一定要是连续的0才有去枚举的意义。从后往前做(好想一点),每次把最后一位如果小于5且不为0就变成5,然后更新一次答案,如果不为0就再变成0,然后更新一次答案。(不管变不变答案是要更新的)

这个做法的正确性的话贪贪就有了。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cstdlib>
 5 #include<algorithm>
 6 #include<cmath>
 7 #include<queue>
 8 #include<set>
 9 #include<map>
10 #include<vector>
11 #include<cctype>
12 using namespace std;
13 
14 int T,L,R;
15 
16 int calc(int x)
17 {
18     while(x%10==0) x/=10;
19     int len=0,d=x%10==5?-1:0;
20     while(x) x/=10,len++;
21     return len*2+d;
22 }
23 void work()
24 {
25     int ans=L,tmp=L,add=1,MIN=calc(L);
26     for(int i=0;i<=8&&tmp<=R;i++) {
27         if(0<tmp/add%10&&tmp/add%10<5) tmp=(tmp/add-tmp/add%10+5)*add;
28         if(tmp<=R&&calc(tmp)<MIN) ans=tmp,MIN=calc(tmp);
29         if(0<tmp/add%10) tmp=(tmp/add-tmp/add%10+10)*add;
30         if(tmp<=R&&calc(tmp)<MIN) ans=tmp,MIN=calc(tmp);
31         add*=10;
32     }
33     printf("%d\n",ans);
34 }
35 int main()
36 {
37     freopen("test.in","r",stdin);
38     freopen("test.out","w",stdout);
39     scanf("%d",&T);
40     for(int i=1;i<=T;i++) {
41         scanf("%d%d",&L,&R);
42         work();
43     }
44     return 0;
45 }

 

posted @ 2018-02-22 12:32  KKKorange  阅读(210)  评论(0编辑  收藏  举报