SDNU_ACM_ICPC_2020_Winter_Practice_1st(山师联赛~)

Planning
机场中飞机起飞序列为 ai(i>=0) 分别表示为: 在 i 时间起飞的飞机被延误后的每分钟代价为 ai
现在前 k 个飞机都被延误了,
求怎么安排飞机起飞才能使得代价最小
要求: 飞机不能比原先的时间提早起飞
输出最小延误时间和每个飞机的起飞时间

思路:使用优先队列,先把k之前的飞机压入优先队列,然后再将剩下的飞机压入队列同时输出优先队列栈顶的飞机,这样可以保证剩下的飞机不比原来的时间提前起飞。
这里有一个小知识点:结构体中重载运算符
重载运算符的格式如下:
bool operator 运算符 (const 结构体名称 b) const
{
return(什么时候这个运算符对结构体成立);//注意对此运算符使用this->元素名;
}
例如:

const int maxn=1e6
struct people{
    std::string name;
    unsigned int age;
    unsigned int height;
    bool operator<(const people & t)
    {
            return name<t.name;//因为我们是在结构体里的直接重载的,
            //所以可以直接调用结构体里的变量,后面的t则需要使用"."运算符;
    }//按照名字的字典序来排序
}pp[maxn];

priority_queue内元素优先级的设置:
(1)基本数据类型的优先级的设置
priority_queue<int, vector, less>q;
其中vetor用来承载底层数据结构堆的容器,less表示数字大的优先级越大,而greater表示数字小的优先级越大。
(2)结构体的优先级设置
注意在结构体中我们重载小于号就可以,如果重载大于号会出现编译错误,因为从数学上来说重载小于号就满足了我们判断大小的需求,特别注意如果是判断f1==f2即判断!(f1<f2)&&!(f2<f1)即可。
在优先级队列与结构体的联合使用中如果想让优先级大的越大return <即可
但是如果想让优先级小的越大return >
本题代码:

#include<iostream>
#include<algorithm>
#include<queue>
#define maxn 300005
using namespace std;
struct f
{
	int x;
	int y;
	bool operator <(const f &v)const
	{
		return x<v.x;
	}
}s[maxn];
int n,k;
int b[maxn]; 
priority_queue<f> p;
int main( )
{
	cin>>n>>k;
	for(int i=1;i<=n;i++)
	{
		cin>>s[i].x;
		s[i].y=i;
	}
	for(int i=1;i<=k;i++)
	{
		p.push(s[i]);
	}
	long long sum=0;
	for(int i=k+1;i<=n+k;i++)
	{
		if(i<=n) p.push(s[i]);
		f avg=p.top();
		p.pop();
		sum+=(long long) (i-avg.y)*avg.x;
		b[avg.y]=i;
	}
	cout<<sum<<endl;
	for(int i=1;i<=n;i++)
	cout<<b[i]<<" ";
	return 0;
}

A题
题意:
题意给你一个n,求最大的分数<1,并且不可约分;
a,b要尽量接近好,所以从a=n/2; b=n-a; 开始枚举
代码:

#include<iostream>
using namespace std;
int n;
int gcd(int a,int b)
{
	return b==0?a:gcd(b,a%b);
}
int main( )
{
	cin>>n;
	int sum1=n/2;
	int sum2=n-sum1;
	if(n%2==0)
	{
		for(int i=sum1,j=sum2;i>=1;i--,j++)
		{
			if(gcd(i,j)==1)
			{
				cout<<i<<" "<<j<<endl;
				break;
		    }
		}
	}
	else
	cout<<sum1<<" "<<sum2<<endl;
	return 0;
}

B题
题意:一个人买房子,喜欢旁边有人住,n为房子个数(呈一排),m为已经居住的人,但是不知道哪个房子已经住人了,输出挨着人的最大和最小可以居住的位子的个数,旁边一定有人住。
题解:先特判一下n等于k和k=0的情况,然后剩下的情况分两种:如果n<=3k那么输出结果n-k,否则输出2k

#include<iostream>
using namespace std;
int n,k;
int main( )
{
	cin>>n>>k;
	int sum1,sum2;
	if(n==k||k==0)
	{
		sum1=0;
		sum2=0;
	}
	else if(n/3>k-1)
	{
		sum1=1;
		sum2=2*k;
	}
	else
	{
		sum1=1;
		sum2=n-k;
	}
	cout<<sum1<<" "<<sum2<<endl;
	return 0;
}

E题
题意:n代表有n个测试样例,下面n组数,注意后面的数的结果是在前面数的结果之上出来的,大概意思就是给你一组数,假设一个数是x,你可以用两个数来替换它,p,x-p,把所有数换成1的是谁,先走的赢输出1,后走的赢输出2。
题解:一个数最终被分解成1一共需要n-1次。

#include<iostream>
using namespace std;
int n;
int a[100005];
int main( )
{
	int count;
	cin>>n;
	for(int i=0;i<n;i++)
	{
		cin>>a[i];
		count+=a[i]-1;
		int flag=0;
		if(count==0)
		flag=1;
		else if(count%2==0)
		{
			flag=1;
		}
		if(flag) cout<<2<<endl;
		else cout<<1<<endl;
	}
	return 0;
}
发布了29 篇原创文章 · 获赞 2 · 访问量 611

猜你喜欢

转载自blog.csdn.net/qq_44722533/article/details/104066002