您的位置:首页 > 其它

腾讯马拉松之 湫湫系列故事——消灭兔子

2014-02-26 15:45 211 查看
                                                                        湫湫系列故事——消灭兔子

题目链接:Click Here~

题目分析:

     题目要求,用最小的花费杀死所有的Rabbits。可以从题意就推测出这是一道贪心题,但是不是普通的做法就可以过了,因为数据太大,所以要用到一些数据结构。

     本题可以用多种算法解题。好像本人暂时知道的有三种,贪心+优先队列,贪心+STL,线段树。我是用贪心+STL做的。如果,对其他做法感兴趣的话可以自己百度。

算法思路分析:

    从贪心的角度分析,我们知道要想最后的花费最少。肯定要每一支箭尽最大的可能去射杀血量最大的兔子,且这支箭的花费又要尽最大可能的小。所以,从这两条要求中我们就可以知道,要先对每只箭的价值从小到大排序,使得尽可能的用价值较小的箭去射杀血量尽可能大的兔子。可以看出朴素的方法在1e5的数据小肯定超时。所以,这里我就想到了将兔子的血量先排序。然后,用排完序的价值中的伤害值去查找可以射杀的最大血量的兔子是多少。每次找到一只可以射杀的兔子后,就将这只兔子删除。这种方法查找下去一定会使花费最小。不理解的要自己好好想想。然后,又偷偷的学习了一下STL中的multiset<>的用法。最后,细节部分就自己看下面的代码吧。第三份代码是根据别人提供的思路,我自己写了一遍,一提交居然是171s。上排行榜前几了!!!!太无语了-_-

#include <iostream>
#include <algorithm>
#include <set>
#include <vector>
#include <cstdio>
#include <cstring>
using namespace std;

const int N = 1e5 + 10;
struct Rabbit{
int hurt,price;
bool operator < (const Rabbit &a)const{
return price < a.price;
}
}list
;
multiset<int> S;
multiset<int>::iterator it;
void Init(int n,int m)
{
int hp;
S.clear();
for(int i = 0;i < n;++i){    //每只兔子的血量
scanf("%d",&hp);
S.insert(hp);
}
for(int i = 0;i < m;++i)     //第i支箭的伤害值
scanf("%d",&list[i].hurt);
for(int i = 0;i < m;++i)
scanf("%d",&list[i].price); //第i支箭的价值
sort(list,list+m);
}
int main()
{
int n,m;
while(~scanf("%d%d",&n,&m))
{
Init(n,m);
int cnt = 0;
__int64 ans = 0;
for(int i = 0;i<m&&cnt<n;++i){
it = S.upper_bound(list[i].hurt);
if(it != S.begin()){
cnt++;
ans += list[i].price;
S.erase(--it);         //可以射杀兔子的最小花费
}
}
if(cnt == n)
printf("%I64d\n",ans);
else
printf("No\n");
}
return 0;
}


#include <iostream>
#include <algorithm>
#include <set>
#include <vector>
#include <cstdio>
#include <cstring>
using namespace std;

const int N = 1e5 + 10;
struct Rabbit{
int hurt,price;
bool operator < (const Rabbit &a)const{
return price < a.price;
}
}list
;
multiset<int> S;
multiset<int>::iterator it;
void Init(int n,int m)
{
int hp;
S.clear();
for(int i = 0;i < n;++i){
scanf("%d",&hp);
S.insert(-hp);
}
for(int i = 0;i < m;++i)
scanf("%d",&list[i].hurt);
for(int i = 0;i < m;++i)
scanf("%d",&list[i].price);
sort(list,list+m);
}
int main()
{
int n,m;
while(~scanf("%d%d",&n,&m))
{
Init(n,m);
int cnt = 0;
__int64 ans = 0;
for(int i = 0;i<m&&cnt<n;++i){
it = S.lower_bound(-list[i].hurt);
if(it != S.end()){
cnt++;
ans += list[i].price; // cout<<"price = " <<list[i].price<<endl;
S.erase(it);
}
}
if(cnt == n)
printf("%I64d\n",ans);
else
printf("No\n");
}
return 0;
}


  优先队列版:

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <vector>
#include <queue>
#include <cstring>
using namespace std;

typedef __int64 LL;
const int N = 1e5 + 5;
struct Rabbit{
int hurt,price;
bool operator <(const Rabbit &a)const{
return price > a.price;
}
}rab
;
bool cmp1(int a,int b)     //兔子的血量排序
{
return a > b;
}
bool cmp2(Rabbit &a,Rabbit &b)   //箭的伤害值排序
{
return a.hurt < b.hurt;
}
int main()
{
int n,m;
while(~scanf("%d%d",&n,&m))
{
int hp;
vector<int> ive;
vector<int>::iterator it;
priority_queue <Rabbit> Q;
for(int i = 1;i <= n;++i){
scanf("%d",&hp);
ive.push_back(hp);
}
for(int i = 1;i <= m;++i)
scanf("%d",&rab[i].hurt);
for(int i = 1;i <= m;++i)
scanf("%d",&rab[i].price);
sort(ive.begin(),ive.end(),cmp1);
sort(rab+1,rab+m+1,cmp2);
LL ans = 0;
int k = m;
for(it = ive.begin();it != ive.end();++it){
while(k&&(*it) <= rab[k].hurt){       //将所有可以杀死第i只兔子的箭都压入到队列中
Q.push(rab[k]);
k--;
}
if(Q.empty())
break;
Rabbit tmp = Q.top();                //获取最小花费的箭
Q.pop();
ans += tmp.price;
}
if(it == ive.end())
printf("%I64d\n",ans);
else
printf("No\n");
}
return 0;
}



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: