百度之星Astar2012程序设计大赛初赛试题及参考答案
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
百度之星Astar2012程序设计大赛初赛试题(第一场)
————及B题答案
比赛说明
百度之星初赛:2012年6月2日、6月3日10:00Am~12:00Pm
本次大赛的初赛的初赛采取在线答题、编译,离线判题的形式,选手报名后,可以在6月2日、6月3日任选一天参加比赛,也可选择两场都参加。
针对每题,交题后,系统将给出程序编译是否正确的结果,但不会给出程序是否通过全部测试数据的评价;当场比赛结束后,所有选手的针对每题所写的程序将被离线评判,每题根据程序通过测试数据的数目计算得分。
每场初赛根据单场所有题目总分计算成绩,选出当场成绩在前400名的选手进入复赛(第一场已经进入复赛的选手参加第二场比赛如果再次晋级,将被不在第二场参与排名)。
2012年6月2日,2012百度之星Astar2012程序设计大赛初赛打开大幕。
这里提供了初赛第一场的题目,供有未进初赛和其它有兴趣的朋友研究。
初赛第一场共4题。
分别是度度熊就是要第一个出场、小小度刷礼品、集合的交与并、轮子上的度度熊。
目录
比赛说明······················· 1·A:度度熊就是要第一个出场·············· 2·B:小小度刷礼品··················· 5·C:集合的交与并····················6·D:轮子上的度度熊···················6·
A:度度熊就是要第一个出场
题目描述
Baidu年会安排了一场时装秀节目。
N名员工将依次身穿盛装上台表演。
表演的顺序是通过一种“画线”抽签的方式决定的。
首先,员工们在一张白纸上画下N条平行的竖线。
在竖线的上方从左到右依次写下1至N代表员工的编号;在竖线的下方也从左到右依次写下1至N代表出场表演的次序。
接着,员工们随意在两条相邻的竖线间添加垂直于竖线的横线段。
最后,每位员工的出场顺序是按如下规则决定的:每位员工从自己的编号开始用手指沿竖线向下划,每当遇到横线就沿横线移动到相邻的竖线上去,直到手指到达竖线下方的出场次序编号。
这时手指指向的编号就是该员工的出场次序。
例如在下图的例子中,度度熊将第二名出场,第一名出场的是员工4。
员工在画横线时,会避免在同一位置重复画线,并且避免两条相邻的横线连在一起。
即下图所示的情况是不会出现的:
给定一种画线的方案,员工编号为K的度度熊想知道自己是不是第一位出场表演的。
如果不是,度度熊想知道自己能不能通过增加一条横线段来使得自己变成第一位出场表演。
输入
为了描述方便,我们规定写有员工编号的方向是y轴正方向(即上文中的竖线上方),写有出场次序的方向是y轴负方向(即上文中的竖线下方)。
竖线沿x轴方向(即上文中从左到右)依次编号1至N。
于是,每条横线的位置都可以由一个三元组<xl, xr, y>确定,其中xl, xr是横线左右两个端点所在竖线的编号,y是横线的高度。
输入第一行是一个整数T(T <= 50),代表测试数据的组数。
每组数据的第一行包含三个整数N, M,K( 1<=N<=100, 0<=M<=1000,
1<=K<=N),分别代表参与表演的员工人数、画下的横线数目以及度度熊的员工编号。
每组数据的第2~M+1行每行包含3个整数, xl, xr, y, (1 <= xl < N, xr = xl + 1, 0 <= y <= 1,000,000),描述了一条横线的位置。
输出
对于每组数据输出一行Yes或者No,表示度度熊能否通过增加一条横线段来使得自己变成第一位出场表演。
如果度度熊已经是第一位出场表演,也输出Yes。
注意,尽管输入数据中员工画的横线高度都是整数,但是度度熊可以在任意实数高度画横线。
此外,度度熊和员工一样,在画横线时需要避免在同一位置重复画线,也要避免两条相邻的横线连在一起。
样例输入
2
4 6 3
1 2 1
1 2 4
1 2 6
2 3 2
2 3 5
3 4 4
4 0 3
样例输出
Yes
No
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
struct node{
int l,r,y;
}line[1010];
struct node1{
int t,b,pos;
}a[1010],b[1010];
bool cmp(node a,node b)
{
return a.y > b.y;
}
bool cmp1(node a,node b)
{
return a.y < b.y;
}
int main()
{
int t,n,m,k,i,j,pos,afi,bfi,h,ha,hb;
bool flag;
scanf("%d",&t);
while(t--)
{
scanf("%d%d%d",&n,&m,&k);
for(i=0;i<m;i++)
{
scanf("%d%d%d",&line[i].l,&line[i].r,&line[i].y);
}
sort(line,line+m,cmp);
pos = k;
afi=0;
h = a[afi].t = 1000000;
while(true)
{
flag = false;
for(i=0;i<m;i++)
{
if(line[i].l==pos&&line[i].y<h)
{
h = a[afi].b = a[afi+1].t = line[i].y;
a[afi].pos = pos;
pos = line[i].r;
afi++;
flag = true;
}
else if(line[i].r==pos&&line[i].y<h)
{
h = a[afi].b = a[afi+1].t = line[i].y;
a[afi].pos = pos;
pos = line[i].l;
afi++;
flag = true;
}
if(flag)
break;
}
if(!flag)
break;
}
a[afi].b = 0;
a[afi].pos = pos;
if(pos==1)
{
printf("Yes\n");
continue;
}
sort(line,line+m,cmp1);
pos = 1;
bfi=0;
h = b[bfi].b = 0;
while(true)
{
flag = false;
for(i=0;i<m;i++)
{
if(line[i].l==pos&&line[i].y>h)
{
h = b[bfi].t = b[bfi+1].b = line[i].y;
b[bfi].pos = pos;
pos = line[i].r;
bfi++;
flag = true;
}
else if(line[i].r==pos&&line[i].y>h)
{
h = b[bfi].t = b[bfi+1].b = line[i].y;
b[bfi].pos = pos;
pos = line[i].l;
bfi++;
flag = true;
}
if(flag)
break;
}
if(!flag)
break;
}
b[bfi].t = 1000000;
b[bfi].pos = pos;
flag = false;
for(i=0,j=bfi;i!=afi&&j!=0;)
{
if(a[i].pos+1==b[j].pos||a[i].pos-1==b[j].pos)
{
flag = true;
break;
}
ha = a[i].b;
hb = b[j].b;
if(ha>hb&&i!=afi)
i++;
else if(hb>ha&&j!=0)
j--;
else
{
if(i!=afi)
i++;
if(j!=0)
j--;
}
}
if(afi==0&&bfi==0)
{
if(k==1)
printf("Yes\n");
else
printf("No\n");
continue;
}
if(flag)
printf("Yes\n");
else
printf("No\n");
}
return 0;
}
B:小小度刷礼品
题目描述
一年一度的百度之星又开始了,这次参赛人数创下了吉尼斯世界纪录,于是百度之星决定奖励一部分人:所有资格赛提交ID以x结尾的参赛选手将得到精美礼品一份。
小小度同学非常想得到这份礼品,于是他就连续狂交了很多次,提交ID从a连续到b,他想问问你他能得到多少份礼品,你能帮帮他吗?
输入
第一行一个正整数T表示数据组数;
接下去T行,每行三个正整数x,a,b (0 <=x <= 1018, 1 <= a,b <= 1018,a <= b)
输出
T行,每行为对应的数据情况下,小小度得到的礼品数
样例输入
1
88888 88888 88888
样例输出
1
#include <stdio.h>
#include <iostream>
using namespace std;
long long fun(int n)
{
long long sum=1;
while (n--)
sum*=10;
return sum;
}
int main()
{
int t;
long long x,a,b;
scanf("%d",&t);
while (t--)
{
scanf("%lld %lld %lld",&x,&a,&b);
long long cnt=0;
int len_x=sizeof(x)/sizeof(int);
int len_a=sizeof(a)/sizeof(int);
int len_b=sizeof(b)/sizeof(int);
for (long long i=a; i<=b; ++i)
{
int len_i=sizeof(i)/sizeof(int);
if (0==(a-x)%fun(len_i-len_x))
{
cnt++;
i+=x;
}
}
printf ("%lld\n",cnt);
}
return 0;
}
C:集合的交与并
对于一个闭区间集合{A1,A2……A K}(K>1,Ai≠A j{i≠j}),我们定义其权值
其中|X|表示X区间的长度;如果X为空集|X|=0。
当然,如果这些闭区间没有交集则权值为0。
给定N个各不相同的闭区间,请你从中找出若干个(至少2个)区间使其权值最大。
输入
第一行一个整数N (2 <= N <= 105)
接下来N行每行两个整数 l r(1<=l<=r<=106),表示闭区间的两个端点。
输出
最大权值
样例输入
4
1 6
4 8
2 7
3 5
样例输出
24
D:轮子上的度度熊
百度楼下有一块很大很大的广场。
广场上有很多轮滑爱好者,每天轮滑爱好者们都会在广场上做一种叫做平地花式轮滑的表演。
度度熊也想像他们一样在轮上飞舞,所以也天天和他们练习。
因为度度熊的天赋,一下就学会了好多动作。
但他觉得只是单独的做动作很没意思,动作的组合才更有欣赏性。
平地花式轮滑(简称平花),是穿轮滑鞋在固定数量的标准桩距间做无跳起动作的各式连续滑行。
度度熊表演的舞台上总共有N个桩,而他也从自己会的动作中挑出M最好看的。
但事情并没有这么简单。
首先每个动作因为复杂度不同,所以经过的桩的个数也不尽相同。
然后,为了保持连贯性,有些动作是接不起来的,所以每个动作都有他前面能接的一个动作的列表。
更有甚者,有的动作要考虑前两个动作才能确定是否能做出来。
因此动作被分为三类:0型动作,无论前面是什么动作都能做出来,所以这种动作也能作为起始动作;1型动作,要考虑前面那个动作才能确定是否能接上;2型动作,要考虑前面两个动作才能确定是否能接上。
最后,评分也很复杂。
每个动作有个单独得分,只要在表演过程中做了这个动作就能获得这个分数。
有些动作的组合也非常好看,也会有相应的得分。
不过要获得某个组合的得分就要在过程中完成这组组合中所有的动作,但是,这些动作既不要求按顺序完成也不要求连续完成。
当然,大家不喜欢重复的动作,所以同一个动作和同一个组合不会获得两次得分。
举个例子,总共有10个桩,有以下几个动作:
动作1:0型,需要3个桩,得分5。
动作2:0型,需要4个桩,得分4。
动作3:1型,能接在动作1或者动作2后面,需要6个桩,得分10。
动作4:2型,要接在动作2+动作1后面,需要4个桩,得分30。
组合1:(动作1,动作2,动作4),得分15。
组合2:(动作1,动作3),得分10。
组合3:(动作2,动作3),得分5。
能配成的方案不少,但有这么几种方案是不行的:
1、动作2+动作1+动作4,虽然,动作4分数很多,而且1,2,4的组合还能额外获得15分。
但是,这个方案总共要用4+3+4=11个桩,超过了总桩数,所以不行。
2、动作1+动作3,同样也完成了一个组合,也满足各个动作要求的限定条件。
但是做完后,只过了9个桩,没有完成整个表演。
这样度度熊会很尴尬的。
所以这样的方案也不行。
最优方案应该是动作2+动作3,满足桩数要求,也满足各个动作前置限定条件。
最后得分:单项动作14分+组合加分5分=19分。
虽然,度度熊一下就算出来自己应该怎么表演了。
但是他还是想考考精通编程的你。
输入
一开始一个整数T(1 <= T <= 5),表示有T组数据,每个数据如下格式:第一行有三个整数,N,M,P。
分别表示桩数、动作数和组合数。
第二行M个0~2的整数,表示每个动作的类型。
第三行M个整数,表示每个动作需要使用的桩数。
第四行M个整数,表示每个动作单项的分数。
接下来P(P<=1024)行,每行描述一个组合。
每行的前两个数X,Y,X表示组合中总共有X个动作,Y表示组合能获得的分数。
后面接X个数,表示组合中包含的X个动作的编号。
再接下来分为M块,第i块描述第i个动作的前置条件。
若第i个动作是0型的,那么它没有前置条件。
所以对应的块是一个空行。
若第i个动作是1型的,对应的块是一个M的01序列。
若这个序列是Aj
的话,Aj=1表示动作i可以接在动作j后面。
若第i个动作是2型的,对应的块是一个MxM的01矩阵。
若这个序列是Aj,k 的话,Aj,k=1表示动作i可以接在动作j+动作k后面。
输出
对于每个数据,输出包含一个整数,表示度度熊能获得的最高分数。
样例输入
1
10 4 3
0 0 1 2
3 4 6 4
5 4 10 30
3 15 1 2 4
2 10 1 3
2 5 2 3
1 1 0 0
0 0 0 0
1 0 0 0
0 0 0 0
0 0 0 0
样例输出
19
提示
保证至少有一个方案满足要求。
对于100%的数据,1≤N≤100,1≤M≤10,所有分数之和在32位有符号整数范围之内。
每个动作至少需要过1个桩。