HDU 4122-Alice's mooncake shop解题报告

本文详细解析了如何使用单调队列解决特定问题,通过样例分析展示了如何优化决策过程,并给出了具体的C++实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这道题要用到单调队列,我们从给出的样例能够看出,区间上很长的一段对当前的决策来说是毫无意义的,最明显的就是比当前的值大的那些值,其实这个也有一点动态规划的思想在里面,我们保证了队首位置的值对当前来说是最优的,很显然这肯定是一个递增的队列,对于当前要加入队列中的元素,我们去掉对于其来说毫无意义的一些值,对于队列中的一个位置i如果其后的一个位置的j的最优值取在了i的位置,也就意味着cost[j]>cost[i]+(j-i)*S,那么对于其后的一个位置k如果有cost[j]+(k-j)*S<cost[k]不等式相加我们可以得到cost[k]>cost[i]+(k-i)*S,而且我们假设cost[j]-cost[i]-(j-i)*S=m以及cost[k]-cost[j]-(k-j)*S=n则cost[k]-cost[i]-(k-i)*S=m+n也就是说队列里的元素从队首至当前要插入的位置对于k来说的优先级别是递减的。也就是说,队首元素就是最优的元素。

View Code
 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #define M 3000
 5 #define N 100005
 6 using namespace std;
 7 _int64 que[N];
 8 _int64 id[N];
 9 _int64 val[M];
10 _int64 t[M];
11 char mon[12][5]={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
12 _int64 getmon(char *s)
13 {
14     _int64 i;
15     for(i=0;i<12;i++)
16         if(!strcmp(s,mon[i]))
17             return i;
18 }
19 _int64 day[12]={31,28,31,30,31,30,31,31,30,31,30,31};
20 bool is(_int64 year)
21 {
22     if(year%400==0||(year%100&&year%4==0))
23         return true;
24     return false;
25 }
26 _int64 alltime(_int64 year,_int64 month,_int64 date,_int64 hour)
27 {
28     _int64 i,j;
29     _int64 ans=0;
30     for(i=2000;i<year;i++)
31     {
32         if(is(i))
33             ans+=366;
34         else
35             ans+=365;
36     }
37     for(i=0;i<month;i++)
38     {
39         if(is(year)&&i==1)
40             ans+=29;
41         else
42             ans+=day[i];
43     }
44     ans+=(date-1);
45     ans*=24;
46     ans+=hour;
47     return ans;
48 }
49 int main()
50 {
51     char mo[5];
52     _int64 n,m;
53     _int64 year,date,hour,month;
54     _int64 S,cost,T;
55     _int64 ans;
56     _int64 i;
57     while(scanf("%I64d%I64d",&n,&m)&&(n||m))
58     {
59         for(i=0;i<n;i++)
60         {
61             scanf("%s%I64d%I64d%I64d%I64d",mo,&date,&year,&hour,&val[i]);
62             month=getmon(mo);
63             t[i]=alltime(year,month,date,hour);
64         }
65         scanf("%I64d%I64d",&T,&S);
66         _int64 top,tail;
67         _int64 fir;
68         top=tail=fir=0;
69         ans=0;
70         for(i=0;i<m;i++)
71         {
72             scanf("%I64d",&cost);
73             while(top<tail&&(que[tail-1]+(i-id[tail-1])*S)>=cost)
74                 tail--;
75             que[tail]=cost;
76             id[tail++]=i;
77             while(fir<n&&t[fir]==i)
78             {
79                 while(top<tail-1&&id[top]+T<t[fir])
80                     top++;
81                 ans+=val[fir]*(que[top]+(t[fir]-id[top])*S);
82                 fir++;
83             }
84         }
85         printf("%I64d\n",ans);
86     }
87     return 0;
88 }

 

转载于:https://www.cnblogs.com/caozhenhai/archive/2012/10/26/2741551.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值