比赛结果如何呢?充满感慨~ 参加这个比赛,发现确实要成功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
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
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
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] 转移过来。
很明显,使用动态规划的方法解决直观明了,开始看题目以为是要数学推导,找规律。