洛谷1090 合并果子
题意·:把两堆放到一堆花费两堆的和体力,将所有堆最后合成一个堆,求最小体力
分析:贪心寻找最小挪法,每次将最小的两堆合在一起
写法1
这个开始ac的后来看题解不晓得为啥能过,大概是数据太弱,大家直接看2把
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<string>
using namespace std;
const int N = 1e5+10;
int n,sum=0;
int a[N];
int main()
{
scanf("%d",&n);
for(int i=0;i<n;i++)scanf("%d",&a[i]);
for(int i=0;i<n-1;i++)
{
sort(a+i,a+n);//每次找最小两个
int x=a[i]+a[i+1];
sum+=x;
a[i+1]=x;
}
printf("%d\n",sum);
return 0;
}
写法2
使用优先队列,非常简单,但是数据大的话可能过不了
每次取最前面的两个数也就是最小
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<string>
#include<queue>
#include<vector>
using namespace std;
int n,sum=0;
priority_queue<int,vector<int>,greater<int> >q;
int main()
{
scanf("%d",&n);
for(int i=0;i<n;i++)
{
int x;
scanf("%d",&x);
q.push(x);
}
for(int i=0;i<n-1;i++)
{
int a=q.top();q.pop();
int b=q.top();q.pop();
sum+=a+b;
q.push(a+b);
}
printf("%d\n",sum);
return 0;
}
题意:两个人比分为a和b 能不能在n个回合达到这个分数(i回合硬,加i分)
分析:先判断是不是能达到a和b的分数的和 1~n的和 等差数列求和
sum=n(n+1)/2* 若可以得到分数,则贪心求出第一个人赢的回合,从大到小寻找 避免回溯
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
//开 long long
long long a,b;
long long sum=0;
int main()
{
scanf("%lld%lld",&a,&b);
long long n=sqrt(2*(a+b));
if(n*(n+1)!=2*(a+b))printf("No\n");//1~n求和 判断是否存在
else
{
printf("%lld",n);
for(long long i=n;a;i--)//从大到小寻找 避免回溯
{
if(i<=a)
{
a-=i;
printf(" %lld",i);
}
}
}
}
P1684 考验
题意: 每段四行诗的韵脚只可能是“AABB”, “ABAB”, “ABBA” 和“AAAA”中的一种。每句诗句的韵脚都编了号,具有相同编号的句子代表有相同的韵脚。现在,黄药师想删掉一些句子,使得剩下的都是遵循押韵规则的四行诗,而且不允许改变诗句的顺序。找出满足条件最长的诗歌
分析:贪心 观察韵脚 两个A和两个B 则sum++ 当A和B相同 也sum++
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
using namespace std;
const int N = 5100;
int n,sum;
map<int,int>m;
int main()
{
int s=0;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
int x;
scanf("%d",&x);
m[x]++;
if(m[x]==2)s++;
if(s==2)//各有两个情况 A B
{
s=0;
sum++;
m.clear();
}
if(m[x]==4)//四个一样 A=B
{
s=0;
sum++;
m.clear();
}
}
printf("%d\n",sum);
return 0;
}
题意:构造a和b 使得ci=(ai+bi)%3 构造最小max(a,b)
分析:贪心 均衡分配数,当给c一个大的数之后,之后大数都给b,最终达到 max最小,其次就是模拟,从最大位开始遍历构造
#include<iostream>
#include<cstdio>
#include<string>
#include<algorithm>
using namespace std;
int t,n;
string a,b,c;
int main()
{
scanf("%d",&t);
while(t--)
{
b=c="";
scanf("%d",&n);
cin>>a;
int flag=0;
for(int i=0;i<n;i++)
{
if(i==0)
{
if(a[i]=='0')b+='1',c+='2',flag=1;
else if(a[i]=='1')b+='2',c+='2';
else b+='1',c+='1';
continue;
}
if(a[i]=='1')
{
if(flag)c+='0',b+='1';
else b+='0',c+='1',flag=1;
}else if(a[i]=='0')b+='0',c+='0';
else if(a[i]=='2')
{
if(flag)b+='2',c+='0';
else b+='1',c+='1';
}
}
cout<<b<<endl;
cout<<c<<endl;
}
return 0;
}
Acwing 3776. 水果拼盘
题意:有四种水果,数量为a b c d,有两种水果拼盘ad和bcd,价格为e和f,怎么搭配可以得到最大利润
分析:利用贪心的思想,两种拼盘都需要用到d,d是题眼,先不考虑d,按照拼盘的水果最多分为,a和min(b,c) ,然后考虑怎样分配d达到最大利润,分为四种情况
- 现有的d大于两种拼盘所需要的d,两种拼盘都可以拼成
- 两种拼盘需要的d都大于现有的d,两种拼盘找最大利润
- 一个需要大于d,一个需要小于d,比较是 都给第一种 | 给第二种给满,剩下的给第一种,哪种利润更高
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
int t;
int a,b,c,d,e,f;
int main()
{
scanf("%d",&t);
while(t--)
{
int sum=0;
scanf("%d%d%d%d%d%d",&a,&b,&c,&d,&e,&f);
int x=a,y=min(b,c);
if(x+y<=d)
sum=x*e+y*f;
else if(x>=d&&y>=d)
sum=max(d*e,f*d);
else if(x>=d)
sum=max(d*e,y*f+(d-y)*e);
else if(y>=d)
sum=max(d*f,x*e+(d-x)*f);
else
sum=max(x*e+f*(d-x),y*f+(d-y)*e);
printf("%d\n",sum);
}
return 0;
}