ACM第三周学习总结
这周做了继续关于贪心算法的一些题。
题目
1:ride to school
【题目描述】
起点与终点相隔4500米。现Charley需要从起点骑车到终点。但是,他有个习惯,沿途需要有人陪伴,即以相同的速度,与另外一个人一起骑。而当他遇到以更快的速度骑车的人时,他会以相应的速度跟上这个更快的人。先给定所有与Charley同路的人各自的速度与出发时间,问Charley以这种方式跟人,骑完4500米需要多少时间。得出的结果若是小数,则向上取整。
代码
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <vector>
#include <map>
#include <queue>
#include <algorithm>
#include <math.h>
#include <cstdio>
using namespace std;
struct f
{
int v,t,t1;
}a[10001];
bool cmp(f a,f b)
{
return a.t1>b.t1;
}
int main()
{
int n,i;
int s=4500;
while(cin>>n)
{
if(n==0) break;
for(i=0;i<n;i++)
{
cin>>a[i].v>>a[i].t;
if(a[i].t<0) {a[i].t1=100000;continue;}
a[i].t1=ceil(4500*3.6/a[i].v)+a[i].t;
}
sort(a,a+n,cmp);
cout<<a[n-1].t1<<endl;
}
}
这道题开始时我想的比较复杂,在遇到最快的人之前,算出Charley跟随的每一个人走的时间及距离,然后用剩下的距离除以最快速度得出跟随最快的人走的时间,再加上之前的时间就是最后Charley到达的时间。但所跟随的每个人走的时间算起来很麻烦。后来发现Charley和最快的人同时到达终点,Charley到达终点的时间就是最快的人到达终点的时间,即最快的人从起点到终点的时间加上他到起点的初始时间。
所以,看到题目后要多思考,当想到的第一个思路比较麻烦时,想想有没有其他思路,不要一有思路就写代码。
这道题还要注意单位的换算,注意精度的问题。这道题要用到ceil函数(函数向上舍入最接近的整数)。
2:HDU 1338 Game Prediction
题意:有m个人,每人得到n张牌,牌的号码是1到n*m之间的任意n个数,每张牌都只有一张,问我至少能赢多少局。
Sample Input
2 5
1 7 2 10 9
6 11
62 63 54 66 65 61 57 56 50 53 48
0 0
Sample Output
Case 1: 2
Case 2: 4
代码
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <vector>
#include <map>
#include <queue>
#include <algorithm>
#include <math.h>
#include <cstdio>
using namespace std;
const int maxn=5000;
int a[maxn],vis[maxn];
int used[maxn];
bool cmp(int a,int b)
{
return a>b;
}
int main()
{
int N,M;
int t=1;
while(cin>>M>>N,M+N)
{
memset(vis,0,sizeof(vis));
memset(used,0,sizeof(used));
int ans=0;
for(int i=0;i<N;i++)
{
cin>>a[i];
vis[a[i]]=1;
}
sort(a,a+N,cmp);
for(int i=1;i<=M*N;i++)
{
if(!vis[i])
for(int j=0;j<N;j++)
{
if(!used[j])
{
if(a[j]<i)
{
++ans;
used[j]=1; break; }
}
}
}
printf("Case %d: %d\n",t++,N-ans);
}
return 0;
}
这道题老师讲过,做作业时又遇到了。我最少赢多少次,转化为最多输多少次,即对方最多赢几次。站在对方的角度,怎么才能尽可能的赢?平时打牌时,如果尽量用小的牌赢得对方大的牌,那么最后打牌胜利的几率越大。 那么将自己的牌降序排列,然后将对方的牌升序排列,对方从最小的牌开始,依次比我的牌(降序排列),找到我的牌中比他小的中最大的,那么对方赢一次,依次遍历完对方所有牌。提交成功后,发现课件上的排序和我的不一样。课件上面,我的牌和对方的牌都是升序排列,然后拿对方最小的牌和我升序的牌比。为什么排序不一样结果一样?我又想了想,发现自己的牌根本不用排序,只要对方是升序的牌我比,结果都一样。这是每一轮都决定胜负的卡牌,而我开始的思路——尽量用小的牌赢得对方大的牌那么最后打牌胜利的几率越大,是针对最后赢一轮的卡牌游戏。所以,对方完全没必要尽量用小牌赢取我大牌。而对方之所以要从小牌开始跟我比,是避免对方的大牌淘汰掉我的小牌后,本能赢我比较大的牌却不能赢或我本来能让对方小牌能赢得牌被他的大牌淘汰导致他的小牌不能赢。
学习收获
-
初步了解了差分 的有关知识(目前初步了解,不列举例题并展开)。
-
memset函数用于内存空间的初始化,可以方便的清空一个结构类型的变量或数组。
如:memset(void *s,int ch,sizeof(n))表示将s中当前位置后面n个字节用ch替换并返回s。 -
ceil函数 ,向上舍入最接近的整数。
-
注意有循环结构时变量的初始化,好几个题因为有循环结构时变量作用域的问题而出错。
感悟
这周课上内容学完了贪心算法,但对贪心算法的深入与理解并未止步于此,以后有时间还会不断通过做题来加深自己对贪心算法的理解与熟练应用。
这周主要是做作业题。作业题目中思路有简单点的,也有比较难的。无论是思路简单的题目还是思路复杂的题目,每个题目都要提交数次乃至数十次才能ac,每一个错误都让人烦恼,但正是这一个个错误,使得最后一次的ac格外得令人愉悦。当然,有些题目无数次提交后还是不能ac,只能去看题解。各种各样的错误原因应接不暇,但每犯一个错误,都要争取下次少犯这样的错误。
这周进行了第一场比赛,只做出来了一道题,但并不能说不满意,因为这是我的起点,没有进行过其他比赛,谈不上遗憾。我相信在这个起点上,我能不断进步,不断超越现在的自己。