CF Good Bye 2015 E. New Year and Three Musketeers(贪心+枚举)
来源:互联网 发布:plc密码破解软件 编辑:程序博客网 时间:2024/05/30 22:54
题目链接:http://codeforces.com/contest/611/problem/E
题意:有三个抢手能力值分别为a,b,c。另外有n个小怪抵抗力为t(i)。当一个抢手能能力值大于等于小怪的抵抗力时抢手可以在一回合内杀死小怪。多个抢手同时联手当其能力值和大于等于某小怪抵抗力时可以再一回合内杀死小怪。问三个抢手最少多少回合能将小怪全部杀死。
解法:先贪心,后枚举。
1.贪心部分:把抢手能力值排序使a<=b<=c,把怪物按抵抗力从低到高排序,看是否a+b+c能消灭所有怪物,不能就输出“-1”。如果能,看是否有必要使用a+b+c。然后看是否有必要使用b+c,每使用一次b+c时,可以使用一次a(使用时发挥a的最大效能)。然后看是否有必要使用a+c,没使用一次a+c,可以使用一次b(发挥最大效能)。贪心部分的回合数为ans。
2.枚举部分:下面就面临着一个问题,如何使用a+b和c,假设a+b能消灭剩余的怪中的x个,c能消灭y个,那么如果只用a+b和c最快可以再max((x+y)/2,y-x,x-y)回合数内消灭全部怪物。那么我们就枚举只单独使用a、b、c的回合数,可以得到使用 a 或 b 或 c 或 a+b 时消灭怪物的最少次数,记为add。
最终的答案就是ans+add。(枚举部分需要体会理解,表示智商低,想了一天才想明白)。
3.实现时的技巧:将小怪抵抗力全部插入一个multiset中,需要查询小于等于某个值的最大抵抗力,而STL中的lower_bound(val)返回的是左开右闭范围中大于等于val的元素的位置,如果范围内全部值都小于val,则返回尾部空指针。这就需要我们在处理抵抗力时将所有抵抗力减一再插入multiset中,这样的好处是查询时只需要查询小于某个值的最大抵抗力,就可以直接使用lower_bound(val)而不需要判断得到的值是否等于val,可以大大减少代码量。
下付两种实现方法,大家可以体会:
1.抵抗力减一再插入:
#include <iostream>#include <cstdio>#include <cstring>#include <string>#include <algorithm>#include <cmath>#include <vector>#include <set>#include <map>#include <stack>#include <queue>#include <iterator>using namespace std;multiset<int> kill;int w[3];multiset<int>::iterator it,it2;int ans;void greedy(int dl,int pre){ while(kill.size()!=0){ it=kill.end(); it--; if(*it<dl) break; kill.erase(it); ans++; it=kill.lower_bound(pre); if(it!=kill.begin()){ it--; kill.erase(it); } }}int main (){ int n; int a,b,c; while(scanf("%d",&n)!=EOF){ scanf("%d%d%d",&w[0],&w[1],&w[2]); sort(w,w+3); kill.clear(); int x; for(int i=1;i<=n;i++){ scanf("%d",&x); x--; kill.insert(x); } it=kill.end(); it--; if(*it>=w[0]+w[1]+w[2]){ printf("-1\n"); continue; } ans=0; greedy(w[1]+w[2],0); greedy(w[0]+w[2],w[0]); greedy(max(w[0]+w[1],w[2]),w[1]); int one=0,two=0; it=kill.begin(); while(it!=kill.end()){ if(*it<w[0]+w[1]) two++; if(*it<w[2]) one++; it++; } int add=n*10; for(int i=0;i<=n;i++){ if(2*min(one,two)>=kill.size()){ add=min(add,i+((int)kill.size()+1)/2); } else{ add=min(add,i+(int)kill.size()-min(one,two)); } for(int j=0;j<=2;j++){ it2=kill.lower_bound(w[j]); if(it2!=kill.begin()){ it2--; if(*it2<w[0]+w[1]) two--; if(*it2<w[2]) one--; kill.erase(it2); } } } printf("%d\n",ans+add); } return 0;}
2.抵抗力直接插入:
#include <iostream>#include <cstdio>#include <cstring>#include <string>#include <algorithm>#include <cmath>#include <vector>#include <set>#include <map>#include <stack>#include <queue>#include <iterator>using namespace std;multiset<int> kill;int w[3];multiset<int>::iterator it,it2;int ans;void greedy(int dl,int pre){ while(kill.size()!=0){ it=kill.end(); it--; if(*it<=dl) break; kill.erase(it); ans++; if(!kill.empty()){ it=kill.lower_bound(pre); if(kill.size()==1){ if(it==kill.end()){ it--; kill.erase(it); } else if(*it<=pre) kill.erase(it); } else{ if(it!=kill.end()&&*it<=pre) kill.erase(it); else{ if(it!=kill.begin()){ it--; kill.erase(it); } } } } }}int main (){ int n; int a,b,c; while(scanf("%d",&n)!=EOF){ scanf("%d%d%d",&w[0],&w[1],&w[2]); sort(w,w+3); kill.clear(); int x; for(int i=1;i<=n;i++){ scanf("%d",&x); kill.insert(x); } it=kill.end(); it--; if(*it>w[0]+w[1]+w[2]){ printf("-1\n"); continue; } ans=0; greedy(w[1]+w[2],0); greedy(w[0]+w[2],w[0]); greedy(max(w[0]+w[1],w[2]),w[1]); int one=0,two=0; it=kill.begin(); while(it!=kill.end()){ if(*it<=w[0]+w[1]) two++; if(*it<=w[2]) one++; it++; } int add=n*10; for(int i=0;i<=n;i++){ if(2*min(one,two)>=kill.size()){ add=min(add,i+((int)kill.size()+1)/2); } else{ add=min(add,i+(int)kill.size()-min(one,two)); } for(int j=0;j<=2;j++){ if(!kill.empty()){ it2=kill.lower_bound(w[j]); if(kill.size()==1){ if(it2==kill.end()){ it2--; if(*it2<=w[0]+w[1]) two--; if(*it2<=w[2]) one--; kill.erase(it2); } else{ if(*it2<=w[j]){ if(*it2<=w[0]+w[1]) two--; if(*it2<=w[2]) one--; kill.erase(it2); } } } else{ if(it2!=kill.end()&&*it2<=w[j]){ if(*it2<=w[0]+w[1]) two--; if(*it2<=w[2]) one--; kill.erase(it2); } else{ if(it2!=kill.begin()){ it2--; if(*it2<=w[0]+w[1]) two--; if(*it2<=w[2]) one--; kill.erase(it2); } } } } } } printf("%d\n",ans+add); } return 0;}
- CF Good Bye 2015 E. New Year and Three Musketeers(贪心+枚举)
- Codeforces Good Bye 2015 E. New Year and Three Musketeers
- codeforces Good Bye 2015 E. New Year and Three Musketeers
- Codeforces GoodBye2015 New Year and Three Musketeers Codeforces 611E(贪心)
- 【转】Codeforces GoodBye2015 New Year and Three Musketeers Codeforces 611E(贪心)
- CF Good Bye 2015 A- New Year and Days(CF611A)
- CF Good Bye 2015 C- New Year and Domino(CF611C)
- CF Good Bye 2015 C. New Year and Domino && D. New Year and Ancient Prophecy (DP)
- CF Good Bye 2015 F. New Year and Cleaning(思维)
- CodeForces 611E New Year and Three Musketeers
- Codeforces 611 E New Year and Three Musketeers
- 【14.94%】【codeforces 611E】New Year and Three Musketeers
- Good Bye 2015-New Year and Old Property(二进制暴力枚举)
- CF Good Bye 2015 B- New Year and Old Property(CF611B)
- Good Bye 2014 E. New Year Domino
- CodeForces Good Bye 2016 :C New Year and Rating、D New Year and Fireworks、E New Year and Old Subsequ
- Codeforces Good Bye 2015 C. New Year and Domino (预处理)
- Good Bye 2015 C New Year and Domino(dp)
- 安卓中color.xml
- Java数字相关
- android 使用字体图标(Icon Font)
- iOS中UITableView性能优化
- Socket编程实践(7) --Socket-Class封装(改进版v2)
- CF Good Bye 2015 E. New Year and Three Musketeers(贪心+枚举)
- ImportError: No module named cv2
- Java-Blob-取出来插入另一个数据库[导库程序]
- Socket编程实践(8) --Select-I/O复用
- Oracle的绿色客户端工具,支持ODBC和PL_SQL
- C++ 11 可变参数宏结合可变参数模板使用!
- HTML5 标准格式
- Socket编程实践(9) --套接字IO超时设置方法
- VS2012鼠标输入光标变成灰色块的解决方法