【HDU5188 BestCoder Round 33C】【贪心排序+DP】zhx and contest 考试不被怀疑作弊条件下达到至少m分的最少时间
2015-11-19 20:52
731 查看
#include<stdio.h> #include<string.h> #include<ctype.h> #include<math.h> #include<iostream> #include<string> #include<set> #include<map> #include<vector> #include<queue> #include<bitset> #include<algorithm> #include<time.h> using namespace std; void fre(){freopen("c://test//input.in","r",stdin);freopen("c://test//output.out","w",stdout);} #define MS(x,y) memset(x,y,sizeof(x)) #define MC(x,y) memcpy(x,y,sizeof(x)) #define MP(x,y) make_pair(x,y) #define ls o<<1 #define rs o<<1|1 typedef long long LL; typedef unsigned long long UL; typedef unsigned int UI; template <class T1,class T2>inline void gmax(T1 &a,T2 b){if(b>a)a=b;} template <class T1,class T2>inline void gmin(T1 &a,T2 b){if(b<a)a=b;} const int N=3e6+10,M=0,Z=1e9+7,ms63=1061109567; int casenum,casei; int n,m; struct A { int t,v,l,st; bool operator < (const A& b)const {return l-t<b.l-b.t;}//按照耽误时间从小到大排序 }a[32]; int f ; int main() { while(~scanf("%d%d",&n,&m)) { LL sumv=0; for(int i=1;i<=n;i++) { scanf("%d%d%d",&a[i].t,&a[i].v,&a[i].l); a[i].st=max(a[i].l,a[i].t);//st表示最早结束时间 sumv+=a[i].v; } if(sumv<m) { puts("zhx is naive!"); continue; } sort(a+1,a+n+1); int sumt=0; int tmpv=0; for(int i=1;i<=n;i++) { sumt=max(sumt+a[i].t,a[i].l); tmpv+=a[i].v; if(tmpv>=m)break; } if(sumt>1e3)while(1); memset(f,0,(sumt+2)*4); for(int i=1;i<=n;i++) { for(int j=sumt;j>=a[i].st;j--)if(f[j]<m)//减少不必要的运算,同时防止爆int { gmax(f[j],f[j-a[i].t]+a[i].v); } } for(int i=0;i<=sumt;i++)if(f[i]>=m) { printf("%d\n",i); break; } } return 0; } /* 【trick&&吐槽】 小心a[i].v累加起来爆int哦 【题意】 T(50)组数据, 对于每组数据,有n(1<=n<=30)个问题, 对于第i个问题,如果我们决定去做,那么会花费ti分钟,然后会获得vi的分数。 然而,对于第i道题而言,其解决时间不能早于li(可以等于),否则会被认定为作弊。 1<=ti,li<=1e5;1<=vi<=1e9. 现在我们问你,他至少在场上待多久才可以在不认定为作弊的条件下得到至少m(0<=m<=1e9)分。 如果无法达成,则输出"zhx is naive!" 【类型】 贪心 DP 【分析】 首先,无法达成的条件是当前分数之和<m,这个特判一下,看看要不要输出"zhx is naive!" 否则,肯定至少有一种方法能够达成目标。 我们发现,这题既要决策做哪些题,又要决策做题顺序。 于是,不如我们先假定要做的题已经确定了,现在只是要考虑做题顺序。 这样就会发现,肯定是按照耽误时间从小到大来安排做题顺序。 于是,现在考虑到题的选择,我们先按照耽误时间从小到大来对所有题目做排序。 我们用f[j]表示在当前距离比赛开始过去了j个时间单位条件下能够获得的最大分数。 那么初始化f[]=0,并且有状态转移方程—— for(int i=1;i<=n;i++) { for(int j=sumt;j>=max(a[i].l,a[i].t);j--)gmax(f[j],f[j-a[i].t]+a[i].v); } 然后枚举一道题做或不做。并且积累在当前时间为j下的分数,记做f[i]。 那么我们就有了状态转移方程gmax(f[i],f[j]+最早从j+1时刻做这道题的最早完成时间) 【时间复杂度&&优化】 O(T*n*sumt),最坏是50*30*30*1e5=45e8的时间复杂度 然而大概是数据太水了,竟然这个复杂度也是可以0msAC的>_<。 */
相关文章推荐
- 1.一些 贪心算法 的简单思维题:
- 贪心算法——字典序最小问题
- 贪心算法——区间调度问题
- Jump Game I,II 贪心
- Wildcard Matching
- 贪心题目循环和控制台折行
- HDOJ 1009
- 【解题报告】【USACO】酸奶工厂
- 【解题报告】【】交谊舞
- POJ 1328
- Best Cow Line
- 贪心 hdu 1003
- 最大容器
- 满足和为定值的两个数或多个数
- Codeforces Round #300
- HUD1052 __ P2 1002 __ Tian Ji -- The Horse Racing
- 2015年国家集训队测试 BZOJ3816矩阵变幻
- poj 1328
- HDU--1052
- POJ 2709 混合颜料 acm 贪心