HDU 4803 Poor Warehouse Keeper (贪心+避开精度)

555555,能避开精度还是避开精度吧,,,,我们是弱菜。。

Poor Warehouse Keeper

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1672    Accepted Submission(s): 463

Problem Description
Jenny is a warehouse keeper. He writes down the entry records everyday. The record is shown on a screen, as follow:
There are only two buttons on the screen. Pressing the button in the first line once increases the number on the first line by 1. The cost per unit remains untouched. For the screen above, after the button in the first line is pressed, the screen will be:
The exact total price is 7.5, but on the screen, only the integral part 7 is shown. Pressing the button in the second line once increases the number on the second line by 1. The number in the first line remains untouched. For the screen above, after the button in the second line is pressed, the screen will be:
Remember the exact total price is 8.5, but on the screen, only the integral part 8 is shown. A new record will be like the following:
At that moment, the total price is exact 1.0. Jenny expects a final screen in form of:
Where x and y are previously given. What’s the minimal number of pressing of buttons Jenny needs to achieve his goal?
 
Input
There are several (about 50, 000) test cases, please process till EOF. Each test case contains one line with two integers x(1 <= x <= 10) and y(1 <= y <= 109) separated by a single space - the expected number shown on the screen in the end.
 
Output
For each test case, print the minimal number of pressing of the buttons, or “-1”(without quotes) if there’s no way to achieve his goal.
 
Sample Input
1 1 3 8 9 31
 
Sample Output
0 5 11
Hint
For the second test case, one way to achieve is: (1, 1) -> (1, 2) -> (2, 4) -> (2, 5) -> (3, 7.5) -> (3, 8.5)
 
Source
 
Recommend
liuyiding
 

一个机器,只有两个按钮,上面的按钮表示数量,下面的表示总价(只显示整数部分)

开始的时候数量和总价都是1,单价为1,然后进行一些操作,让数量变成x,总价变成y,求得是最小操作次数。

如果按数量键,表示增加一个物品,单价不变,数量+1,那么总价=总价/数量*(数量+1),并且显示新的数量

如果按总价键,单价=(总价+1)/数量,那么总价=总价+1,并且显示总价的整数部分。

 

x很小y很大,暴力宽搜TLE了。

换个角度,求最小操作次数 换成  求最小合法单价的操作次数

因为最终得到了x数量,y的总价,对于一个单价tp,如果tp*x的整数部分==y那么这个单价就是可以的。

而最小操作次数一定是 得到最小合法单价的操作次数。

对于两种操作,按数量键并不会影响单价,按总价键会增加单价,而且增加单价的幅度是随着操作次数增多而下降的,按下数量键会是这个幅度下降的更多。

这样,一共要按下x-1次数量键,每次按数量键前尽量多的按总价键(保证该单价下的x个数量物品不会超过y元),最后会得到一个不超过目标单价(y/x)的最大单价z,该单价下的总价值为z*n如果z*n<y则还需要按下若干次总价键。

 

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdlib>
 4 #include<cstdio>
 5 #include<algorithm>
 6 #include<cmath>
 7 #include<queue>
 8 #include<map>
 9 #include<set>
10 #include<string>
11 //#include<pair>
12 
13 #define N 1005
14 #define M 1000005
15 #define mod 1000000007
16 #define inf 0x3f3f3f3f
17 //#define p 10000007
18 #define mod2 100000000
19 #define ll long long
20 #define LL long long
21 #define maxi(a,b) (a)>(b)? (a) : (b)
22 #define mini(a,b) (a)<(b)? (a) : (b)
23 
24 using namespace std;
25 
26 ll mul=3628800;
27 ll x,y;
28 ll ans;
29 ll tmi,tma;
30 ll dmi,dma;
31 ll dan;
32 ll num,tot;
33 
34 void ini()
35 {
36     ans=0;
37     tmi=y*mul;
38     tma=(y+1)*mul;
39     dmi=tmi/x;
40     dma=tma/x;
41     num=1;
42     dan=mul;
43     tot=mul;
44 }
45 
46 
47 void solve()
48 {
49     ans=x-1;
50     ll k1,k2;
51     ll te;
52     if(dan>=dma){
53         ans=-1;return;
54     }
55     for(num=1;num<=x;num++){
56         te=mul/num;
57         if(dan>=dmi) break;
58         k1=(dmi-dan+te-1)/te;
59         k2=(dma-dan+te-1)/te;
60       //  printf(" num=%I64d ans=%I64d dan=%I64d dmi=%I64d dma=%I64d te=%I64d k1=%I64d k2=%I64d\n",
61 //               num,ans,dan,dmi,dma,te,k1,k2);
62         if(k1!=k2){
63             ans+=k1;
64             dan+=k1*mul/num;
65             return;
66         }
67         else{
68             dan+=(k1-1)*te;
69             ans+=(k1-1);
70         }
71     }
72 }
73 
74 void out()
75 {
76     printf("%I64d\n",ans);
77 }
78 
79 int main()
80 {
81     //freopen("data.in","r",stdin);
82     //freopen("data.out","w",stdout);
83     //scanf("%d",&T);
84    // for(int ccnt=1;ccnt<=T;ccnt++)
85    // while(T--)
86     while(scanf("%I64d%I64d",&x,&y)!=EOF)
87     {
88         //if(n==0 && k==0 ) break;
89         //printf("Case %d: ",ccnt);
90         ini();
91         solve();
92         out();
93     }
94 
95     return 0;
96 }

 

posted on 2014-10-16 11:30  njczy2010  阅读(568)  评论(0编辑  收藏  举报