题目描述
田忌和齐威王又开始赛马了,这一次齐威王为了增加难度,在每一匹马上都设置了一个刀币值,如果田忌赢了这匹马,那么他就可以获得相应的刀币,否则他就要失去相应的刀币(平局田忌也要失去刀币)。现在齐威王和田忌各有n匹马,每匹马有一个速度值,齐威王的每匹马还有一个刀币值,速度快的马会获得胜利,速度相同则是平局。现在齐威王已经排好了马的顺序,请你帮助田忌排兵布阵,并计算出他最多可以赢得多少刀币?(如果最后是输钱就请输出负数)。
例如:当有n=3匹马的时候
齐威王三匹马的速度为40, 30, 20
三匹马对应的刀币值为 1,2,3
田忌三匹马的速度为 20,30,50
齐威王的马顺序固定,田忌可以随意调动马匹出场顺序
当田忌出场顺序为 20,50,30 的时候
田忌会先失去一个刀币,再获得两个刀币,再获得三个刀币,故最后田忌赢得四个刀币,输出4,如果输了x个刀币就输出x的负数。输入描述:
输入第一行包含一个整数T,代表测试案例个数。(5<=T<=10)
接下来每个测试案例都包括四行
第一行为一个整数n(0<n<=1000),代表马的个数。
第二行为n个整数,代表齐威王各匹马的速度。
第三行为n个整数,代表齐威王各匹马的刀币值(0<刀币值<=100),与速度值一一对应。
第四行为n个整数,代表田忌各匹马的速度。(0<速度值<=100)
输出描述:
输出田忌最多可以赢得的刀币值。
示例1
输入
2
3
40 30 20
1 2 3
20 30 50
5
25 25 50 60 10
10 50 5 100 30
70 5 30 25 40
输出
4
185
题解 :
贪心
首先将田忌和齐威王的马的速度非递减排序
对于田忌的马 i 来说 将齐威王所有速度小于马i的马放进优先队列.
从中选择分值最大的.
这样对于 田忌的马 i + 1 来说,还在优先队列中的小于马i速度的马也满足小于马i+1
于是最后弹出来的都是田忌的马能战胜的,且其获得的分值也是最多的.
最后队列里剩下的还有剩下没放进队列的都是田忌输掉的马.最后减去即可.
这样的算法复杂度是O(n+m)
而这题n的大小O(n^2)也能解决
这样的问题已经很多次了
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e3+10;
struct House{
ll speed,val;
bool operator < (const House &a) const {
return speed < a.speed;
}
};
House wang[maxn];
ll tian[maxn];
priority_queue<int,vector<int>,less<int> > qu;
int main()
{
int caset;scanf("%d",&caset);
while(caset--)
{
while(!qu.empty()) qu.pop();
int n;scanf("%d",&n);
for(int i=0;i<n;i++) scanf("%lld",&wang[i].speed);
for(int i=0;i<n;i++) scanf("%lld",&wang[i].val);
for(int i=0;i<n;i++) scanf("%lld",&tian[i]);
sort(wang,wang+n);sort(tian,tian+n);
ll ans = 0;
int pos = 0;
for(int i=0;i<n;i++) {
while(pos < n && wang[pos].speed < tian[i]) qu.push(wang[pos++].val);
if(qu.empty()) continue;
ans += qu.top();
qu.pop();
}
/// 2333 忘了还有没有遍历完的
while(pos < n) qu.push(wang[pos++].val);
while(!qu.empty()) ans -= qu.top(),qu.pop();
printf("%lld\n",ans);
}
return 0;
}