记HL某一次个人ACM赛

为什么ACM赛变成了个人赛……


NO.1

BBQ Easy

题目不给给出处吧:AtCoder 1979

思路

这道题有一个很明显的贪心,由于两串肉串的容肉数是由最短的棒决定的,所以必须保证两根木棒的长度差最小,所以只需将其排序,然后取短的累加即可。

代码如下

#include<bits/stdc++.h>
using namespace std;
int a[1001];
long long s=0;
int main()
{
	int n;
	cin>>n;
	for(int i=1;i<=2*n;i++)
	 cin>>a[i];
	sort(a+1,a+2*n+1);
	for(int i=1;i<=2*n;i+=2)
	 s+=a[i];
	cout<<s<<endl;
	return 0;
}

(这题看着简单,我理解题目理解了半年……)


NO.2

Memory and Trident

CodeForces 712B

思路

首先必须明确,走奇数步是不可能回到原点的,然后,由于要回到原点,所以向两个方向相反的方向走的步数必须相同,两方向的步数差相加就是最少改变的步数的两倍。
代码如下

#include<bits/stdc++.h>
using namespace std;
int l=0,r=0,u=0,d=0,sum=0,x,s1;
int main()
{
	string s;
	cin>>s;
	s1=s.size();
	if(s1%2!=0)//走奇数步一定不可能回到原点
	{
		cout<<-1<<endl;
		return 0;
	}
	x=s1/4;
	for(int i=0;i<=s1-1;i++)//统计向各个方向走的步数
	{
		if(s[i]=='L') l++;
		if(s[i]=='R') r++;
		if(s[i]=='U') u++;
		if(s[i]=='D') d++;
	}
	//保证向左和向右走的步数相同,向上和向下走的步数相同
    if(l!=r) 
    {
    	sum+=abs(l-r);
    }
    if(u!=d)
    {
    	sum+=abs(u-d);
    }
    cout<<sum/2<<endl;//左右的步数差相加是应该改变的两倍
	return 0;
}

由于没有判断清楚能走回原地的步数,导致我交了好多次都没有AC,下面的一半代码倒是改了半天


NO.3

Tea Party

CodeForces 808C

思路

首先我们应该保证每杯水都倒满一半,满足第一个条件,如果倒完后所剩的水为负,那么说明给定的水无法满足第一个条件,输出-1。若还有剩余,则可利用循环加水,需满足体积大的杯子装水多所以从体积大的杯子开始加,每次都加满,如果所剩的水无法加满,那么将水都倒入这个杯中,结束循环。最后再按照原输入顺序输出即可。
代码如下:

#include<bits/stdc++.h>
using namespace std;
int a[1010],b[1010],s=0,k;
struct bbb
{
	int a,b,c;
}bb[1010];
bool cmp(bbb x,bbb y)
{
	return x.a>y.a;
}
bool mycmp(bbb g,bbb h)
{
	return g.c<h.c;
}
int main()
{
	int n,x;
	cin>>n>>x;
	for(int i=1;i<=n;i++)//先满足前两个条件,给每个杯子加一半的水
	{
	 cin>>bb[i].a;
	 if(bb[i].a%2==0)
	 {
	  bb[i].b=bb[i].a/2;
	  x-=bb[i].b;
     }
	 else
	 {
	  bb[i].b=bb[i].a/2+1;
	  x-=bb[i].b;
	 }
	 bb[i].c=i;
    }
    sort(bb+1,bb+n+1,cmp);//按照杯子体积排序
    if(x<0)//如果剩下的水是负数,说明无法满足每个杯子倒一半体积的水的条件,输出-1
    {
    	cout<<-1<<endl;
    	return 0;
    }
    if(x>0)
    {
    	for(int i=1;i<=n;i++)
    	{
    		x-=bb[i].a-bb[i].b;//将体积大的杯子倒满水
    		bb[i].b=bb[i].a;//此时杯子里的水是水的体积
    		if(x<0)//若小于0,说明无法倒满,现在水的体积即为一半的体积加所剩的水
    		{
    			bb[i].b+=x;
    			x=0;
    			break;//无水可倒,跳出循环
    		}
    	}
    }
    sort(bb+1,bb+n+1,mycmp);//将被子恢复到开始的顺序输出
	for(int i=1;i<=n-1;i++)
	 cout<<bb[i].b<<' ';
	 cout<<bb[n].b<<endl;
    return 0;
}

NO.4

Buns

思路:

多重背包模版题,但是我同桌用资源分配AC了,将所有的物品转化为最多可用n[i]个,每个都有v[i]的价值,w[i]的花费,然后套模版即可(老师分析时这样讲的,然而我好像并没有深刻理解)
本题不附代码


NO.5

Appleman and Toastman

思路:

递推题。经递推可以得出,最大的价值是每次都去掉最小的那个数,那么也不难推出,先将其从大到小进行排序,从最大值开始求前缀和,每一次最大值只累加一次,而其余前缀都会累加两次,此时为最优解。

代码如下:

#include<bits/stdc++.h>
using namespace std;
long long a[301010]={},sum=0,b[301010]={};
bool cmp(int x,int y)//从大到小排序
{
	return x>y;
}
int main()
{
	long long n;
	cin>>n;
	for(long long i=1;i<=n;i++)
	{
	 cin>>a[i];
	 sum+=a[i];//第一次累加全部
    }
	 b[0]=0;
	sort(a+1,a+n+1,cmp);//将a数组进行排序,方便统计由大到小的前缀和
	for(long long i=1;i<=n;i++)
	 b[i]=a[i]+b[i-1];//求前缀和
	for(long long i=2;i<=n;i++)
	 sum+=b[i];//除唯一一个最大值只累加一次,其余数都累加两次(前面已经进行一次累加)
	cout<<sum<<endl;
	return 0;
}

注意数据范围,因为这个修改了思路,然而一次又一次wa掉


At last

Lakes in Berland

思路:

dfs搜索出湖泊的大小并用一个点存在结构体中,最后又num[0]个湖泊,再按湖泊大小排序需要填的湖泊是前n-k个,然后dfs得出结果
(只有分析,没有代码)


本次比赛,得出以下结论:
1.考试时应该看清题目,理解透然后再做。
2.考虑方面要充分,不能少判断或错判断
3.数据范围坑死人啊~
4.递归递推是基础

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值