HDU4415(枚举,贪心)
大意:
杀手有把耐久为m的“袖口刀”,一共有n个敌人,每个敌人都有防御值Ai ,杀死一个为Ai的敌人则m -= Ai,每个敌人有“能量刀”,杀死敌人后可以获取敌人的能量刀,能量值Bi是几就可以再杀几个人,刀可以叠加,Bi为0就是这个敌人没有能量刀。问消耗尽量小的m,最多可以杀多少敌人。
题解:
把敌人按照Bi分为a组和b组,a组的敌人都是没有能量刀的敌人(Bi=0),b组的Bi>0。
枚举1、只用袖口刀杀a组里的人,能杀多少是多少,杀完若m还有剩余,则尝试去杀b组的人,若能杀掉一个防御最低的,用得到的能量刀就能把b组的人全杀掉。
例如数据:
1
5
7 1
7 1
1 0
1 0
1 0
枚举2、仅用袖口刀去杀b组的人,不用能量刀,直到剩余的m值不够用了,在用能量刀接着杀,若能杀完,在用能量刀和袖口刀去杀a组的人
例如数据:
1
6 20
10 2
10 2
100 0
100 0
100 0
100 0
枚举3、用袖口刀杀掉b组防御最低的(杀不掉则回到枚举1),然后用得到的能量刀杀完b组的人,在用袖口刀和能量刀杀a组的人
例如数据:
1
5 5
10 1
4 1
5 2
100 0
1 0
然后比较3种枚举得到的值,得出答案,貌似贪心思想没大用到。。。
#include <iostream> #include <vector> #include <algorithm>
#define FOR(a,b) for(int i = (a);i < (b);i ++) using namespace std; struct Enemy { int Ai,Bi; }; bool cmp(const Enemy& a,const Enemy& b) { return a.Ai < b.Ai; } struct Ans { int num,cost; }; bool operator<(const Ans& a,const Ans& b) { if(a.num == b.num) return a.cost > b.cost; return a.num < b.num; } vector<Enemy> b; vector<int> a; Ans afirst(int m) { Ans ans; ans.cost = 0,ans.num = 0; for(int i = 0; i < a.size() && m >= a[i];i ++) { m -= a[i]; ans.num ++; ans.cost += a[i]; } if(!b.empty() && m >= b[0].Ai) ans.num += b.size(),ans.cost += b[0].Ai; return ans; } Ans bfirst(int m,int energy) { Ans ans; ans.num = 0,ans.cost = m; for(;ans.num < b.size() && m >= b[ans.num].Ai;ans.num ++) m -= b[ans.num].Ai; ans.cost -= m; energy -= b.size() - ans.num; if(energy >= a.size()) ans.num = a.size()+b.size(); else{ ans.num = b.size() + energy; for(int i = 0;i <= a.size() - energy && a[i] <= m;i ++) ans.num ++,ans.cost += a[i],m -= a[i]; } return ans; } Ans banda(int m,int energy) { Ans ans; ans.num = 0,ans.cost = 0; ans.cost += b[0].Ai; m -= ans.cost; energy -= b.size() -1; if(energy >= a.size()) ans.num = a.size() + b.size(); else { ans.num = b.size() + energy; for(int i = 0;i <= a.size() - energy && a[i] <= m;i ++) ans.num ++,ans.cost += a[i],m -= a[i]; } return ans; } int main() { int n,m,num,cost,energy; Enemy enemy; Ans ans,ans1,ans2,ans3; int testcases; scanf("%d",&testcases); for(int ca = 1; ca <= testcases; ca ++) { a.clear(),b.clear(); num = 0,cost = 0; energy = 0; scanf("%d%d",&n,&m); FOR(0,n) { scanf("%d%d",&enemy.Ai,&enemy.Bi); if(enemy.Bi) b.push_back(enemy),energy += enemy.Bi; else a.push_back(enemy.Ai); } if(!b.empty()) sort(b.begin(),b.end(),cmp); if(!a.empty()) sort(a.begin(),a.end()); if(a.empty())//每个敌人都有剑 { if(m >= b[0].Ai) printf("Case %d: %d %d\n",ca,b.size(),b[0].Ai); else printf("Case %d: 0 0\n",ca); continue; } //枚举1 只用自己的武器在a中杀人 ans1 = afirst(m); //枚举2 只用自己的武器杀b中的人 ans2 = bfirst(m,energy); //枚举3 杀一个b中的,用敌人的武器搞死完b,然后搞a ans3 = banda(m,energy); ans = ans1 < ans2 ? ans2 : ans1; ans = ans < ans3 ? ans3 : ans; printf("Case %d: %d %d\n",ca,ans.num,ans.cost); } }