P1223 排队接水
思路
让接水时间短的人站前面,结构体排序即可。 较多的贪心都是这种比较简单的…比如P1208 P2240
实现
#include <iostream>
#include <algorithm>
using namespace std;
struct people{
int t;
int ind;
}a[1001];
bool cmp(struct people a,struct people b)
{
if(a.t == b.t)
return a.ind<b.ind;
else
return a.t<b.t;
}
int main(){
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i].t;
a[i].ind = i;
}
sort(a+1,a+n+1,cmp);
double ans = 0.0;
for(int i=1;i<=n;i++)
{
cout<<a[i].ind<<" ";
ans+=a[i].t*(n-i);
}
cout<<endl;
printf("%.2f\n",ans/n);
return 0;
}
P1803 凌乱的yyy / 线段覆盖
思路
将所有区间按照区间终点从小到大排序,使用pos记录上一次参加比赛的结束时间,下一场比赛是否参加,只需要将pos与要参加的比赛的开始时间进行比较
实现
#include <iostream>
#include <algorithm>
using namespace std;
struct line{
int st;
int end;
}a[1000010];
bool cmp(struct line a,struct line b)
{
if(a.end == b.end)
return a.st>b.st;
else
return a.end<b.end;
}
int main(){
int n;
cin>>n;
for(int i=0;i<n;i++)
{
cin>>a[i].st>>a[i].end;
}
sort(a,a+n,cmp);
int ans = 0;
int pos = -1;
for(int i=0;i<n;i++)
{
if(pos<=a[i].st)
{
ans++;
pos = a[i].end;
}
}
cout<<ans;
return 0;
}
P5019 [NOIP2018 提高组] 铺设道路
思路
–
实现
#include<bits/stdc++.h>
using namespace std;
int n,a[100005];
long long ans=0;
int main()
{
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=2;i<=n;i++) if(a[i]>a[i-1]) ans+=a[i]-a[i-1];
cout<<ans+a[1];
return 0;
}
P1090 [NOIP2004 提高组] 合并果子
思路
用priority_queue,每次弹出两个最小的相加,再把结果push进去。
实现
#include<bits/stdc++.h>
using namespace std;
int n,x,ans;
priority_queue<int,vector<int>,greater<int> >q;
int main(){
cin>>n;
for(int i=1;i<=n;i++) cin>>x,q.push(x);
while(q.size()>=2){
int a=q.top(); q.pop();
int b=q.top(); q.pop();
ans+=a+b;
q.push(a+b);
}
cout<<ans<<endl;
return 0;
}
P1106 删数问题
思路
- 从最高位开始,遇到一个数字比后一个数字大的话就删去。
- 最后处理前导零,如果全是前导零就输出0
实现
#include <stdio.h>
#include <string.h>
char c[260];
int main(){
int len,i,j,s;
scanf("%s%d",c,&s);
len=strlen(c);
while(s--){
for(i=0;i<=len-2;i++)
if(c[i]>c[i+1]){
for(j=i;j<=len-2;j++)
c[j]=c[j+1];
break;
}
len--;
}
i=0;
while(i<=len-1&&c[i]=='0')i++;
if(i==len)printf("0");
else
for(j=i;j<=len-1;j++)
printf("%c",c[j]);
return 0;
}
P4995 跳跳!
思路
这道题的贪心策略是:第一次跳到最高的石头,然后跳到其他石头里最低的石头,再跳到其他石头里最高的石头…
实现
#include<iostream>
#include<cstdio>
#include<queue>
#include<algorithm>
#define maxn 301
using namespace std;
long long n,a[301],ans,sum,num,l=0;
int main() {
scanf("%lld",&n);
for(int i=1; i<=n; i++)
scanf("%lld",&a[i]);
sort(a+1,a+n+1);
while(num<n)
{
if(l<=n/2) sum+=(a[l]-a[n-l])*(a[l]-a[n-l]),l=n-l;
else sum+=(a[l]-a[n-l+1])*(a[l]-a[n-l+1]),l=n-l+1;
num++;
}
printf("%lld",sum);
return 0;
}
P4447 [AHOI2018初中组]分组
思路
参考了题解
- 通过维护两个数组来模拟队列,last数组记录队列的最后一个数字,len数组记录队列的长度。
- 先对所有数从小到大排序,然后对于每一个数,找到last数组里记录的最后一个数字等于该数减1且len最小的,修改last[j]和len[j]
- 最终返回最小的len[j]即可
实现
#include<bits/stdc++.h>
using namespace std;
int last[100010];
int len[100010];
int a[100010];
int main()
{
int n;
int cnt = 0;
cin>>n;
for(int i=0;i<n;i++)
cin>>a[i];
sort(a,a+n);
for(int i=0;i<n;i++)
{
int minlen = 100010;
bool find = 0;
int pos = 0;
for(int j=0;j<cnt;j++)
{
if(last[j]==a[i]-1 && len[j]<minlen)
{
minlen = len[j];
pos = j;
find = 1;
}
// cout<<"i:"<<i<<" a[i]:"<<a[i]<<" len[j]:"<<len[j]<<" last[j]"<<last[j]<<" j:"<<j<<" find:"<<find<<endl;
}
if(!find)
{
last[cnt] = a[i];
len[cnt] = 1;
cnt++;
}
else
{
last[pos] = a[i];
len[pos]++;
}
}
int min_ = 100010;
for(int i=0;i<cnt;i++)
min_ = min(min_,len[i]);
cout<<min_;
return 0;
}
P1080 [NOIP2012 提高组] 国王游戏
思路
–
实现
–
欢迎指正-