贪心进阶
xuanxiao2024 · · 个人记录
AT_abc137_d
首先这一题不能拿背包写,
我们可以想到从前往后填。
而且先贪时间,后贪钱(拿不到工资的贪钱干吗?)。
- 如果贪时间长,如果有时间很短的但是价值很高呢?
- 如果贪时间短,如果有时间很长的但是价值很高呢?
所以,发现从前往后填是错误的(贪心都贪心不起来)。
那我们能不能从后往前填呢?
我们在第
每次找到可以在这里填的数,贪钱即可。
Code
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <queue>
using namespace std;
typedef long long ll;
struct node{
ll a,b;
};
ll n,m,ans;
node a[100005];
priority_queue<ll,vector<ll>,less<ll> > pq;
bool cmp(node a,node b){
if(a.a == b.a) return a.b > b.b;
return a.a < b.a;
}
int main(){
cin >> n >> m;
for(int i = 1;i <= n;i++){
cin >> a[i].a >> a[i].b;
}
ll t = 1;
sort(a + 1,a + 1 + n,cmp);
for(int i = 1;i <= m;i++){
while(t <= n && a[t].a <= i){
pq.push(a[t].b);
t++;
}
if(pq.size() > 0){
ans += pq.top();
pq.pop();
}
}
cout << ans;
return 0;
}
AT_abc123_d
Two种代码。
首先
Mr.蒋
考虑最优情况。
在第
所以如果
所以就可淘汰掉大量情况。
Mr.陈
先暴力求出
记得排好序
后面的情况一定是建立在这时候的前
Code
我第一次想到的思路是 Mr.蒋 的,所以我的代码版本也是 Mr.蒋 的
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <queue>
using namespace std;
typedef long long ll;
priority_queue<ll> pq;
ll x,y,z,m,a[1005],b[1005],c[1005];
bool cmp(ll a,ll b){
return a > b;
}
int main(){
cin >> x >> y >> z >> m;
for(int i = 1;i <= x;i++) cin >> a[i];
for(int i = 1;i <= y;i++) cin >> b[i];
for(int i = 1;i <= z;i++) cin >> c[i];
sort(a + 1,a + 1 + x,cmp);
sort(b + 1,b + 1 + y,cmp);
sort(c + 1,c + 1 + z,cmp);
for(int i = 1;i <= x;i++){
if(i > m) break;
for(int j = 1;j <= y;j++){
if(i * j > m) break;
for(int k = 1;k <= z;k++){
if(i * j * k > m) break;
pq.push(a[i] + b[j] + c[k]);
}
}
}
for(int i = 1;i <= m;i++){
cout << pq.top() << "\n";
pq.pop();
}
return 0;
}
P9525
这一题首先就是贪心,贪每科最高分。
但是会有一些情况就不能选
考虑这种情况,正常我们应该选
但是
题目中有一句话 : 每个成员都有自己的优势,这意味着每个成员都有一项能力值严格大于其他两人的对应能力值。
看到这个 严格大于 没有,这就说明这种情况是非法的。
那我就把 2 给弹出去。
我称这种情况为
还是上面这张图,我弹到后面,就出现了以下情况
你发现才被删掉的2又重回最大了!
为了防止这样的情况,我们再拿个 vis 数组标记这个数有没有被删,如果最大被删过了,直接弹出。
这一题由于是动态的,所以用优先队列
结构体优先队列
我以前是这么写的:
struct node{
int x,y;
};
bool operator < (node a,node b){
if(a.x == b.x) return b.y < a.y;
return b.x < a.x;
}
但老师告诉我,如果结构体多起来,就有点麻烦了。
struct node{
int x,y;
};
struct node_2{
int x,y;
};
node :: friend bool operator < (node a,node b){
if(a.x == b.x) return b.y < a.y;
return b.x < a.x;
}
所以我们一般定义在结构体内部
struct node{
int x,y;
bool operator < (const &b) const{
if(x == b.x) return b.y < y;
return b.x < x;
}
};
struct node_2{
int x,y;
};
Code
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <queue>
using namespace std;
typedef long long ll;
struct node{
ll x,id;
bool operator < (const node& a) const{
return a.x > x;
}
};
priority_queue<node> X,Y,Z;
ll n,x[150005],y[150005],z[150005];
bool vis[1500005];
void work(){
node a = X.top();
node b = Y.top();
node c = Z.top();
if(vis[a.id] == 1){
X.pop();
return ;
}
if(vis[b.id] == 1){
Y.pop();
return ;
}
if(vis[c.id] == 1){
Z.pop();
return ;
}
if(x[b.id] == a.x){
Y.pop();
vis[b.id] = 1;
return ;
}
if(x[c.id] == a.x){
Z.pop();
vis[c.id] = 1;
return ;
}
if(y[a.id] == b.x){
X.pop();
vis[a.id] = 1;
return ;
}
if(y[c.id] == b.x){
Z.pop();
vis[c.id] = 1;
return ;
}
if(z[a.id] == c.x){
X.pop();
vis[a.id] = 1;
return ;
}
if(z[b.id] == c.x){
Y.pop();
vis[b.id] = 1;
return ;
}
cout << a.x + b.x + c.x << "\n";
exit(0);
return ;
}
int main(){
cin >> n;
for(int i = 1;i <= n;i++){
cin >> x[i] >> y[i] >> z[i];
X.push({x[i],i});
Y.push({y[i],i});
Z.push({z[i],i});
}
while(X.size() > 0 && Y.size() > 0 && Z.size() > 0) work();
cout << "-1\n";
return 0;
}