1. 月饼
贪心就行了
三个东西,一个Pair<int,int>,可以用结构体写。这里自带了排序规则
sort函数,相信应该都知道
reverse,翻转,可以理解为数组头变数组尾,好处是默认排序时可以不指定排序方式,排完reverse即可
#include<bits/stdc++.h>
#define endl "\n"
//#define int long long
#define AC return
#define pleaseqwq 0
using namespace std;
const int N=2e5+10;
typedef pair<double,double>PII;
typedef pair<string,int>PSI;
typedef pair<double,double>pdd;
PII a[N];
signed main(){
//cin.tie(0),cout.tie(0);
//ios::sync_with_stdio(false);
int n,d;
cin>>n>>d;
for(int i=0;i<n;i++){
cin>>a[i].second;
}
for(int i=0;i<n;i++){
cin>>a[i].first;
a[i].first/=a[i].second;
}
sort(a,a+n);
reverse(a,a+n);
double res=0;
int cnt=0;
for(int i=0;i<n;i++){
if(cnt+a[i].second<d){
res+=a[i].first*a[i].second;
cnt+=a[i].second;
}else{
res+=(d-cnt)*a[i].first;
break;
}
}
printf("%.2f",res);
AC pleaseqwq;
}
2. 汽车加油问题
我是小丑,第一眼还以为是dp,结果就贪心就好了
果然dp是我最差的部分啊,甚至都一眼看不出来不是dp题
贪心就行了
#include<bits/stdc++.h>
//#define int long long
#define endl "\n"
#define fir for(int i=1;i<=n;i++)
#define rif for(int i=n;i>=1;i--)
#define AC return
#define pleaseqwq 0
using namespace std;
typedef pair<int,int>PII;
typedef pair<string,int>PSI;
typedef pair<string,string>PSS;
unordered_map<string,int>si;
unordered_map<int,int>ii;
const int N=3e3+10;
int a[N];
signed main(){
cin.tie(0),cout.tie(0);
ios::sync_with_stdio(false);
int n,k;
cin>>n>>k;
for(int i=1;i<=k+1;i++) cin>>a[i];
int cnt=0,sum=0;
bool success=true;
for(int i=1;i<=k+1;i++){
if(sum+a[i]<=n) sum+=a[i];
else{
if(a[i]>n) success=false;
else sum=a[i],cnt++;
}
}
if(success) cout<<cnt<<endl;
else cout<<"No Solution!"<<endl;
AC pleaseqwq;
}
3 会场安排问题
好像在哪里做过这道题。。
我们以结束时间来判断,判断最早结束时间前是否有多的活动
有的话,就多开会场即可
(好像是牛客?忘了。。。花了一段时间找了找写过的题,没有,但是好熟悉,应该是以前做过类似的题,在哪里忘了)
#include<bits/stdc++.h>
//#define int long long
#define endl "\n"
#define fir for(int i=1;i<=n;i++)
#define rif for(int i=n;i>=1;i--)
#define AC return
#define pleaseqwq 0
using namespace std;
typedef pair<int,int>PII;
typedef pair<string,int>PSI;
typedef pair<string,string>PSS;
unordered_map<string,int>si;
unordered_map<int,int>ii;
const int N=3e3+10;
int l[N],r[N];
signed main(){
cin.tie(0),cout.tie(0);
ios::sync_with_stdio(false);
int n;
cin>>n;
fir cin>>l[i]>>r[i];
int cnt=0;
//判断最早结束的活动结束前是否有其它活动
//有则必须添加场馆,无则不需
sort(l+1,l+n+1);
sort(r+1,r+n+1);
int j=1;
for(int i=1;i<=n;i++){
if(r[j]>l[i]) cnt++;
else j++;
}
/*
我们假设[1,3][2,4][1,4][3,5]四组数据
直接排序,得到[1,1,2,3]和[3,4,4,5]
对第一个3来说,最早结束是3,但最早开始时间是1,说明至少要多占用一个会场
往下走,继续判断,此间最早结束是3,但仍然是1,再多占用
再往下走,继续判断,最早2,仍然多占用
此时占用了三个
再往下,此时3并不大于3,说明可以紧挨着,那么这个时间就可以放到最早结束的第一个场馆
然后考察第二个最早结束的时间即可,可以放的话,我们就放他后面,往后同理
*/
cout<<cnt<<endl;
AC pleaseqwq;
}
4 程序存储问题
简单贪心没必要多说吧。。
#include<bits/stdc++.h>
//#define int long long
#define endl "\n"
#define fir for(int i=1;i<=n;i++)
#define rif for(int i=n;i>=1;i--)
#define AC return
#define pleaseqwq 0
using namespace std;
typedef pair<int,int>PII;
typedef pair<string,int>PSI;
typedef pair<string,string>PSS;
unordered_map<string,int>si;
unordered_map<int,int>ii;
const int N=3e3+10;
int a[N];
signed main(){
cin.tie(0),cout.tie(0);
ios::sync_with_stdio(false);
int n,l;
cin>>n>>l;
fir cin>>a[i];
sort(a+1,a+n+1);
int sum=0,cnt=0;
for(int i=1;i<=n;i++){
if(sum+a[i]<=l) sum+=a[i],cnt++;
else break;
}
cout<<cnt<<endl;
AC pleaseqwq;
}
5 工厂机器安排
翻译:m个任务,第i个花xi时间,难度为yi,低于难度yi或花费时间xi超过工作时长的机器无法完成任务。完成任务得到500xi+2yi的钱。每台机器每天只能完成一个任务,任务只能被完成一次。
求完成任务最多的方案。同种方案下,赚钱多的优先。多组样例。
首先,我们排序的时候一定是尽量完成花费时间久的任务,同时间下难度高的优先
但同时我们要选择能完成的机器中尽量差的机器
换言之,我们需要记录所有能完成任务的机器,在这些机器中从当前任务所需难度往上找,直到能找到能完成的任务。
显然此时任务应当从花费时间长到短排序。
贪心题,难也确实难。
#include<bits/stdc++.h>
#define int long long
#define endl "\n"
#define fir for(int i=1;i<=n;i++)
#define rif for(int i=n;i>=1;i--)
#define AC return
#define pleaseqwq 0
using namespace std;
typedef pair<int,int>PII;
typedef pair<string,int>PSI;
typedef pair<string,string>PSS;
unordered_map<string,int>si;
unordered_map<int,int>ii;
const int N=2e5+10;
//m:machine,t:task
PII machine[N];
PII task[N];
int cnt[N];
//同种情况下,尽量完成花费时间长的,难度大的。
//同时选用最差的能完成的机器
//可以用重载运算符写
bool cmp(const PII &a, const PII &b){
return a.first==b.first?a.second>b.second:a.first>b.first;
}
signed main(){
cin.tie(0),cout.tie(0);
ios::sync_with_stdio(false);
int n,m;
while(cin>>n>>m){
for(int i=0;i<n;i++) cin>>machine[i].first>>machine[i].second;
for(int i=0;i<m;i++) cin>>task[i].first>>task[i].second;
sort(machine,machine+n,cmp);
sort(task,task+m,cmp);
int res=0,sum=0;
//j是机器,i是任务
for(int i=0,j=0;i<m;i++){
//将所有工作时间大于所需时间的机器找出来
while(j<n&&machine[j].first>=task[i].first){
//记录机器能够解决的对应难度
cnt[machine[j].second]++;
j++;
}
//任务难度上限100
for(int k=task[i].second;k<=100;k++){
//遍历所有任务难度,找任务难度对应最低的那个机器
//如果不存在,由于是按照完成时间顺序排的,其价值更大
//此时找能完成的机器,即难度对应大于他的
if(cnt[k]){
cnt[k]--;
res++;
sum+=500*task[i].first+2*task[i].second;
break;
}
}
}
cout<<res<<' '<<sum<<endl;
}
AC pleaseqwq;
}
是否存在难度权重更大呢?
答,不存在。因为假设任务时间不一样,那么每多一份任务时间,上升500的价值。而难度顶天也就100。所以难度权重一定小于时间。
最后一次实验过几天发吧,半年多没刷算法题了,头疼,写的时候速度大不如前。。。。。我是fw