2020年百度之星程序设计大赛-初赛一(Drink、GPA、Dec)

比赛结果如何呢?充满感慨~ 参加这个比赛,发现确实要成功accept有点难度,算是见识到了,还是ACM大佬厉害。表情图
小白直接上题目了。
Drink
Problem Description
我们有 n 种不同的饮料,每种饮料有无限多瓶,第 i 种饮料一瓶提供 x[i] 毫升的水分,包含 y[i] 卡路里。

现在我们需要选择一种饮料一直喝,直到补充了至少 mm 毫升的水分,我们想使得摄入的卡路里总和最小。请求出这个最小值。
一旦打开一瓶饮料,就一定要喝完。

Input
第一行一个整数 test(1≤test≤100) 表示数据组数。 对于每组数据,第一行两个整数 n,m(1≤n≤100,1≤m≤10000)。 接下来 nn 行,每行两个整数x[i],y[i] (1≤x[i],y[i]≤100)。

Output
对于每组数据,一行一个整数表示答案。

Sample Input
2
1 10
3 3
2 10
3 3
2 1
Sample Output
12
5

一看到题目,感觉跟0-1背包问题很类似,所以我尝试了动态规划的方法,结果本地测试没问题,提交竟然wrong answer。调试好一会,用了直接的思路解决问题。
Accept代码:

#include<bits/stdc++.h>
using namespace std;
int main()
{
	int m;  
	cin>>m;
	while(m--)
	{
		int n, c, num=100000;
		cin>>n>>c;
		
		for(int i = 1; i <= n; i++)
		{
			int x, y; 
			cin>>x>>y;
			if(c%x==0)
				num = min(num,c/x*y);
			else 
				num = min(num,(c/x+1)*y);
		}
		cout<<num<<"\n";
	}
	return 0;
}

目前官方提示:对于每一种饮料,都可以算出最少需要多少瓶,从而知道最少摄入多少卡路里,从中找个最优值。
回头看当时的做法,思路差不多一样,直接明了。

GPA
Problem Description
小沃沃一共参加了 4 门考试,每门考试满分 100 分,最低 0 分,分数是整数。

给定四门考试的总分,请问在最优情况下,四门课绩点的和最高是多少?

分数与绩点之间的对应关系如下:

95~100 4.3
90~94 4.0
85~89 3.7
80~84 3.3
75~79 3.0
70~74 2.7
67~69 2.3
65~66 2.0
62~64 1.7
60~61 1.0
0~59 0

Input
第一行一个正整数 test(1 \le test \le 401)test(1≤test≤401) 表示数据组数。 接下来 testtest行,每行一个正整数 xx 表示四门考试的总分 (0≤x≤400)。

Output
对于每组数据,一行一个数表示答案。答案保留一位小数。

Sample Input
2
0
400
Sample Output
0.0
17.2

Accept代码:

#include<bits/stdc++.h>
using namespace std;
double maxnum;
const int N=11;
int low_g[N]={95,90,85,80,75,70,67,65,62,60,0};//每档次绩点对应最低分
double scores[N]={4.3,4.0,3.7,3.3,3.0,2.7,2.3,2.0,1.7,1.0,0};//绩点 
double score_to_grade(double score)//根据分数得出相应绩点 
{
	if(score>=95)
		return scores[0];
	else if(score>=90)
		return scores[1];
	else if(score>=85)
		return scores[2];
	else if(score>=80)
		return scores[3];
	else if(score>=75)
		return scores[4];
	else if(score>=70)
		return scores[5];
	else if(score>=67)
		return scores[6];
	else if(score>=65)
		return scores[7];
	else if(score>=62)
		return scores[8];
	else if(score>=60)
		return scores[9];
	else
		return scores[10];
}
void dfs(int i,int sum,double score)//深度搜索 
{
	if(sum<0)
		return;
	if(i==3)//最多4门课
	{
		maxnum=max(maxnum,score_to_grade(sum)+score);//取最大绩点和 
		return ;
	}
	for(int j=0;j<N;j++)//循环,枚举每门课的分数档次能够获得的绩点 
		dfs(i+1,sum-low_g[j],score+scores[j]);//深度搜优先索
}
int main()
{
	int r,total;
	cin>>r;
	while(r--)
	{
		cin>>total;
		maxnum=0;
		dfs(0,total,0);
		cout<<setiosflags(ios::fixed)<<setprecision(1);//保留一位小数 
		cout<<maxnum<<'\n';
	}
	return 0;
}

目前官方提示:暴力做法:枚举四门课的成绩,按规则算算GPA。 优秀做法:对于每一档绩点,分数取最低一定是最优的,那么我们就可以用枚举分数的档次取代枚举具体的分数。
这个思路觉得不是暴力做法,对给定的总成绩,深度优先搜索,枚举出每门课的分数档次能够获得的绩点,进行递归,最后取最大绩点和。

Dec

Problem Description
初始有 a, b两个正整数,每次可以从中选一个大于 1 的数减 1,最后两个都会减到 1,我们想知道在过程中两个数互质的次数最多是多少。
Input
第一行一个正整数test(1≤test≤1000000) 表示数据组数。
接下来 test 行,每行两个正整数 a,b(1≤a,b≤1000)。
Output
对于每组数据,一行一个整数表示答案。

Sample Input
1
2 3
Sample Output
4

样例解释
2 3 -> 1 3 -> 1 2 -> 1 1

Accept代码:

#include<iostream>
using namespace std;

const int n_max=1005;
int test;
int a,b;

int f[n_max+1][n_max+1];
int gcd(int a,int b)//辗转相除求最小公约数
{
    int temp=a;
    while(a%b)
    {
        a=b;
        b=temp%b;
        temp=a;
    }
    return b;
}
void dp()
{
    for(int i=1;i<=n_max;i++)//动态规划 
    {
        for(int j=1;j<=n_max;j++)
        {
            int t=0;
            if (gcd(i,j)==1)//如果最大公约数是1则互质
            	t=1;
            f[i][j]=max(f[i-1][j]+t,f[i][j-1]+t);//取最大值 
        }
    }
}
int main()
{
    cin>>test;
    dp();
    for(int k=0; k<test; k++)
    {
	    scanf("%d%d",&a,&b); //输入用cin/cout都会超时
	    printf("%d\n",f[a][b]);
    }

}

官方提示:用 f[i][j]f[i][j] 表示第一个数字从 ii 开始减,第二个数字从 jj 开始减的情况下最多有多少对互质的数字,f[i][j]f[i][j] 从 f[i-1][j]f[i−1][j] 或 f[i][j-1]f[i][j−1] 转移过来。
很明显,使用动态规划的方法解决直观明了,开始看题目以为是要数学推导,找规律。

猜你喜欢

转载自blog.csdn.net/Charzous/article/details/107450175