ACM——作业总结一(ACM罚时+Cleaning Shifts(区间问题))

呐~这学期选修了ACM课,就把一些有意思的题目记录下来吧!(啊学长说我没继续做寒假集训有点小难过哼唧最近还在看python真的是觉得有点压力……虽然都说python简单,但是我这个小白完全不知道有哪些python语句……这不还是很难吗!!!痛苦……)

题目描述 ACM罚时

作为一个ACMer,总是习惯于在比赛中或比赛结束后查看自己的排名(Standing),有细心的同学发现Penalty(罚时),在相同做题数下Penalty越小越好(真是个令人振奋的发现)。让我们看看Penatly的计算方法:每道试题用时将从竞赛开始到试题解答被判定为正确(AC)为止,其间每一次提交运行结果被判错误的话将被加罚20分钟时间,未正确解答的试题不记时。例如:A、B两队都正确完成两道题目,其中A队提交这两题的时间分别是比赛开始后1:00和2:45,B队为1:20和2:00,但B队有一题提交了2次。这样A队的Penalty为1:00+2:45=3:45而B队为1:20+2:00+0:20=3:40,所以B队因Penalty少而获胜。当然如果你AC了某道题后,之后这一题所有提交的代码都不算罚时和时间(有时我也这么无聊~)。恰逢周赛,在九楼机房18:00-22:00,考验随之而来——现在需要你计算大家的Penalty,Penalty初始为00:00,作为ACMer相信你一定可以的!

输入

输入包含多组数据,每组数据的第一行包含一个正整数N(1=<N<=20)表示此ACMer的提交次数,接下来的第2到N+1行表示每次提交的状态,由三个字段组成,第一个字段为一个整数A,表示当前的时间:hour:minutes(保证18=<hour<=22,0<=minutes<=60),第二个字段为一个大写字母(A~Z),表示题号,第三个字段表示OJ返回的状态,假设只可能是AC,WA,RE,TLE中的一种,均为大写

输出

输出这位ACMer的Penalty,每个测试数据占一行

样例输入 Copy

3
18:05 A RE
19:11 A AC
20:00 B WA
1
20:27 F AC

样例输出 Copy

01:31
02:27

思路:
利用sign[ ]数组是否为1来确定此题目是否AC;sign和pen的数组下标都用acsii码记录,方便控制同一道题

#include <bits/stdc++.h>
 using namespace std;
 struct Node{
 	int h;//小时 
 	int m;//分钟 
 	char n;//题目 
 };
 int main()
 {
 	int num,a,b,c;
 	string s;//状态 
 	while(cin>>num)
 	{
 	   int sign[30]={0};//初始化 
	   int pen[30]={0};
	   Node node;//结构体命名 
	   node.h=0;//回到0 
	   node.m=0;
	   for(int i=0;i<num;i++){
	   	scanf("%d:%d",&b,&c);
	   	cin>>node.n;
	   	cin>>s;
	   	a=node.n-'A';//转化成acsii码再相减方便 
	   	if(sign[a]==0)//这道题没被AC 
	   	{
	   		if(s=="AC")
	   		{
	   			node.h+=b-18;//和之前的小时累加 
	   			node.m+=c;//和之前的 
	            sign[a]=1;
			   }
		   else
		     pen[a]++;//罚时记录 
	   }
    }
    for(int i=0;i<30;i++){
    	if(sign[i])//确定了AC 
    	{
    		node.m+=pen[i]*20;
		}
	}
	node.h+=node.m/60;//每满60min进位 
	node.m%=60;//取余直接知道剩下的min
	printf("%02d:%02d\n",node.h,node.m);//注意格式 
}
	 return 0;
 }

题目描述 Cleaning Shifts

Farmer John is assigning some of his N (1 <= N <= 25,000) cows to do some cleaning chores around the barn. He always wants to have one cow working on cleaning things up and has divided the day into T shifts (1 <= T <= 1,000,000), the first being shift 1 and the last being shift T. Each cow is only available at some interval of times during the day for work on cleaning. Any cow that is selected for cleaning duty will work for the entirety of her interval. Your job is to help Farmer John assign some cows to shifts so that (i) every shift has at least one cow assigned to it, and (ii) as few cows as possible are involved in cleaning. If it is not possible to assign a cow to each shift, print -1.

输入

Line 1: Two space-separated integers: N and T * Lines 2…N+1: Each line contains the start and end times of the interval during which a cow can work. A cow starts work at the start time and finishes after the end time.

输出

Line 1: The minimum number of cows Farmer John needs to hire or -1 if it is not possible to assign a cow to each shift.

样例输入 Copy

3 10
1 7
3 6
6 10

样例输出 Copy

2

思路:
这道题的关键在于确定区间的覆盖问题。可以想象一条x轴,那么每头奶牛的工作时间就可以在x轴上确定两点,中间被全部覆盖。我们需要求得的就是能够把x轴全部覆盖的所需要的奶牛数量。先把各个x排序,排除掉最简单的情况(代码中最开始时间不是1,以及第一头牛就实现全覆盖),然后比较y的大小关系。在保证x不与前一个y脱离的情况下,通过y的大小关系来把y拓展到最远。在最远的y中可以得到所需要的奶牛数。

#include <bits/stdc++.h>
 using namespace std;
 struct node{
 	int x,y;
 }q[25005];
 bool cmp(node x,node y)//先比较结构体中x的大小,按升序排列,如果x相同,比较y的大小,按升序排列 
 {
 	if(x.x!=y.x) return x.x<y.x;
 	else
 	 return x.y<y.y;
 }
 int main()
 {
 	int n,t,num=1;
 	scanf("%d %d",&n,&t);//n是奶牛数,t是时间段长度 
 	for(int i=0;i<n;i++){
 		scanf("%d %d",&q[i].x,&q[i].y);
	 }
	sort(q,q+n,cmp);//按照cmp的安排进行排序 
	if(q[0].x!=1){//如果最开始的时间点不是1,那么肯定不能全覆盖 
		printf("-1\n");
	}
	else if(q[0].x==1&&q[0].y>=t){//很明显第一个奶牛工作时间就实现了全覆盖 
		printf("1\n");
	}
	else{//开始最难的中间时间判断!!!! 
		int yi=q[0].y;//用yi记录第一头奶牛的结束时间 
		for(int i=1;i<n&&yi<t;i++){
			num++;//num记录所需要的最小奶牛数 
			int er=yi;//这一步er的意义需要联系下面来看
			if(q[i].x>yi+1){//如果某个x大于了之前一头牛的y,那么中间有空缺时间,不能实现全覆盖 
				printf("-1\n");
				return 0;
			}
			while(q[i].x<=yi+1&&i<n){//保证此时的x和上一步的y没有脱离,并且i在n之内 
				er=max(er,q[i].y);//取最大的y值,这样可以减少不必要的奶牛数(也就是时间范围在前一头奶牛时间内的奶牛) 
				i++;
			}
			yi=er;//把得到的符合上述条件的最大y赋值给yi,继续循环 
		}
		if(yi<t)//如果最后得到的最大y小于t,很明显没全覆盖 
		printf("-1\n");
		else
		printf("%d",num);
	}
	return 0;
 }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值