贪心算法题

国王游戏

  • 贪心策略:大胆假设小心求证
  • 从样例出发:
    • 不难看出除第一次外小涵选择 都是行或者列中最大的
    • 由于电脑永远会选走能构成最大的组合->对于这一行或列:小涵永远选到的是第二大的组合&&电脑也拿不到最大的组合->使得小涵的默契值最大的话:永远选择的是第二大的组合
  • 贪心策略:小涵永远选择能第二大的组合的数(由于行列对称 先选行还是列无影响)
  • 答案就是所有数中第二大的数
  • 贪心证明:电脑拿不到最大的组合&&小涵拿到第二大 所以小涵永远拿到的是最大的且一定赢过电脑
#include<iostream>
#include<algorithm>
using namespace std;
int map[505][505];
int main()
{
	int n;
	cin>>n;
	int max=0;
	for(int i=1;i<n;i++)
	{
		for(int j=i+1;j<=n;j++)
		{
			cin>>map[i][j];//构建样例解释用的图
			map[j][i]=map[i][j];
		}
	 } 
	 //找出第二大的数!!
	for(int i=1;i<=n;i++)
	{
		sort(map[i]+1,map[i]+1+n);//找出每一行第二大的数
		if(max<map[i][n-1])
		max=map[i][n-1];//找出第二大的数
	}
	cout<<"1"<<endl<<max;
	return 0;
}

独木桥

  • 两个问:最小&&最大
  • 最小:
    • 所有人朝着最快到达的方向走【此时一定不会反向】
    • 同时进行:max{到达两边最快的时间}->找出最大的最小
  • 最大
    • 两个人反向->从宏观上看并没有改变方向【可以直接看成两个人交叉走过】->所有人朝着最慢到达的方向走
    • 同时进行:max{最慢的时间}->找出最大的最大
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
	int l;
	cin>>l;
	int n;
	cin>>n;
	int a[5005],b[5005],c[5005];
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
		b[i]=min(a[i],l+1-a[i]);//最小
		c[i]=max(a[i],l+1-a[i]);//最小
	}
	sort(b+1,b+1+n);//最大的最小
	sort(c+1,c+1+n);//最大的最大
	cout<<b[n]<<" "<<c[n];
	return 0;
 } 

排队接水

  • 每个人的等待时间是前面的人打水的时间和->对于总时间相当于第一人打水时间的n-1 +…;
  • 要使越前打水的人时间越短->从小到大排序
#include<bits/stdc++.h>
using namespace std;
int main()
{
	int t;
	long long sum=0,a[1005],b[1005];
	cin>>t;
	for(int i=1;i<=t;i++)
	{
		cin>>a[i];
		b[i]=a[i];
	}
	sort(a+1,a+1+t);
	for(int i=1;i<=t;i++)
	{
		if(i!=t)
		sum+=a[i]*(t-i);
		for(int j=1;j<=t;j++)
		{		

			if(a[i]==b[j])
			{
			cout<<j;
			b[j]=0;
			break;
		    }
		    
		}
		if(i!=t)
		cout<<" "; 
	}
	cout<<endl;
	printf("%0.2f",sum*1.0/t);
	return 0;
}

合并果子

  • 题目很简单:留意一项优先队列的用法
  • 每两个和就是体力和:找到最小的合并【记得更新】每执行一次更新一次->使用优先队列更方便
#include<bits/stdc++.h>
using namespace std;
int main()
{
	int n;
	cin>>n;
	priority_queue<int,vector<int>,greater<int> > q;
	for(int i=1;i<=n;i++)
	{
		int a;
		cin>>a;
		q.push(a);
	}
	int nz;
	int ans=0;
	while(!q.empty())
	{
		int nx=q.top();
		q.pop();
		int ny=q.top();
		if(!q.empty())
		{
		ny=q.top();
		q.pop();
		}
		else continue;
		ans+=nx+ny;
		q.push(nx+ny);
	}
	cout<<ans;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值