week 6 贪心

这周出了四道贪心算法的题,直接让我松一口气。(终于不需要用到我知识盲区里的东西了,除了第四道)

三国游戏

题干很长啊(后面几题都是这样)。总而言之就是,你不能把每一行(每一列)最大的默契值对应的两个武将都抢到, 但是可以抢到次大的(因为电脑把最默契武将的另一半抢走以后又到你选了)。

那么答案就很好想了,给每行(每列)次大的数排个序,然后取最大的那个就是答案了。

什么?你问我机器人会不会赢?

既然我们和机器人都抢不到最大的(可能没看到题目说了小涵先手?),而我们又能拿到次大中的最大,那肯定是我们赢喽。

来看代码: 

#include<bits/stdc++.h>
using namespace std;
int a[505][505];//re在空间太小是我没想到的...
int N,ans;
int main() 
{   
    cin>>N;
    for(int i=0;i<N;i++)
    {
    	for(int j=i+1;j<N;j++)
    	{
    		cin>>a[i][j];
    		a[j][i]=a[i][j];
		}
	}//这个图表的表达倒是整体让我想的时间最长的
	for(int i=0;i<N;i++)
	{
		sort(a[i],a[i]+N,greater<int>());//找次大
		if(ans<a[i][1]) ans=a[i][1];//次大中最大的
	}
	cout<<1<<endl;//肯定是小涵赢啊
	cout<<ans;
	return 0;
}

 

独木桥

这道题有两问,一问最少多久,一问最大要多久。

最少多久很好想,各回各家呗,都往最近的出口方向跑。那么给每个人需要的时间排个序,最大值就是最少需要的时间。

脑子得转个弯才能想明白最大多久怎么处理

我本来想当然的认为,只要找两个相聚最远的人,让他们相向而行,最后出去的人所花的时间就是最大时长,但模拟了一下发现有问题。细想一下才发现,如果按我说的那样执行,所用的时间就是:两人间,距离最远出口更远的人,往最远出口方向跑出,所需要的时间。既然如此,最大时间自然是每个人都往最远的出口跑,再给每个人排序得到的最大值。

来看代码:

#include<bits/stdc++.h>
using namespace std;
int s[100005],b[100005];//数据又开小了...
//s数组代表较小,b代表较大
int L,N,now;
int main() 
{   
    cin>>L>>N;
    int k=0;
    for(int i=0;i<N;i++)
    {
    	cin>>now;
    	if(now<L-now+1) 
    	{
			s[k]=now;
			b[k]=L-now+1;
		}
		else
		{
            s[k]=L-now+1;
			b[k]=now;
		}
		k++;
	}
	sort(s,s+N,greater<int>());//矮子里面挑高个
	sort(b,b+N,greater<int>());//高个里面挑高个
	cout<<s[0]<<" "<<b[0];
	return 0;
}

 

 排队接水

 看题目没什么问题,看题干第一眼就笑喷了。这不跟给我们发的教学视频里面的例题一模一样嘛,输入样例都没改过,只是题目名字换了而已。

一边笑一边提交代码,好家伙直接给我零分。

再瞅一眼题干,好吧,还得输出最优状态下的排队顺序。

没事,稍微加点东西就ac了。

代码:

#include<bits/stdc++.h>
using namespace std;
int N,T[1005],a[1005];//a数组是用来记录位次的
double ans;
int main() 
{   
    cin>>N;
    for(int i=1;i<=N;i++) 
	{
		cin>>T[i];
		a[i]=T[i];
	}
    sort(T+1,T+1+N);
    for(int i=1;i<=N;i++)
    {
    	for(int j=1;j<=N;j++)
    	{
		  if(a[j]==T[i])
		  {
		  	cout<<j;
		  	a[j]=-1;
		    break;
		  }	
		}
		if(i!=N) cout<<" ";
    	  else cout<<endl;
	}//完成排队
    double tot=0;
    for(int i=1;i<=N;++i) 
    tot+=T[i]*(N-i);//贪心
    ans=tot/N;
    cout<<setiosflags(ios::fixed)<<setprecision(2)<<ans;
	return 0;
}

 

合并果子

我看这周题单的概述里面说,这个第四题要用到优先队列,然后先去了解了一下,这道题就变成了一道水题。

如果我没学优先队列,这会估计还在用数组疯狂TLE。

思路很明确,每次合并后都让最小的再合并。如果放到代码里,那就是把两个最小值读出来以后删掉,把它们的和再塞入优先队列里。

说是优先“队列”,可本质上是容器啊,一开始还弄混了。

看代码:

#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()>1)
	{
		int a=q.top();
		q.pop();
		int b=q.top(); 
		q.pop();
		ans+=a+b;
		q.push(a+b);
	}
	cout<<ans<<endl;
	return 0;
}

本周内容就是这些了,学了新知识的同时练了脑子,强度刚好能接受。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

无用夜宵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值