CCCC-GPLT L3-014. 周游世界 团体程序设计天梯赛

周游世界是件浪漫事,但规划旅行路线就不一定了…… 全世界有成千上万条航线、铁路线、大巴线,令人眼花缭乱。所以旅行社会选择部分运输公司组成联盟,每家公司提供一条线路,然后帮助客户规划由联盟内企业支持的旅行路线。本题就要求你帮旅行社实现一个自动规划路线的程序,使得对任何给定的起点和终点,可以找出最顺畅的路线。所谓“最顺畅”,首先是指中途经停站最少;如果经停站一样多,则取需要换乘线路次数最少的路线。

输入格式:

输入在第一行给出一个正整数N(<= 100),即联盟公司的数量。接下来有N行,第i行(i=1, …, N)描述了第i家公司所提供的线路。格式为:

M S[1] S[2] … S[M]

其中M(<= 100)是经停站的数量,S[i](i=1, …, M)是经停站的编号(由4位0-9的数字组成)。这里假设每条线路都是简单的一条可以双向运行的链路,并且输入保证是按照正确的经停顺序给出的 —— 也就是说,任意一对相邻的S[i]和S[i+1](i=1, …, M-1)之间都不存在其他经停站点。我们称相邻站点之间的线路为一个运营区间,每个运营区间只承包给一家公司。环线是有可能存在的,但不会不经停任何中间站点就从出发地回到出发地。当然,不同公司的线路是可能在某些站点有交叉的,这些站点就是客户的换乘点,我们假设任意换乘点涉及的不同公司的线路都不超过5条。

在描述了联盟线路之后,题目将给出一个正整数K(<= 10),随后K行,每行给出一位客户的需求,即始发地的编号和目的地的编号,中间以一空格分隔。

输出格式:

处理每一位客户的需求。如果没有现成的线路可以使其到达目的地,就在一行中输出“Sorry, no line is available.”;如果目的地可达,则首先在一行中输出最顺畅路线的经停站数量(始发地和目的地不包括在内),然后按下列格式给出旅行路线:

Go by the line of company #X1 from S1 to S2.
Go by the line of company #X2 from S2 to S3.
……
其中Xi是线路承包公司的编号,Si是经停站的编号。但必须只输出始发地、换乘点和目的地,不能输出中间的经停站。题目保证满足要求的路线是唯一的。

输入样例:
4
7 1001 3212 1003 1204 1005 1306 7797
9 9988 2333 1204 2006 2005 2004 2003 2302 2001
13 3011 3812 3013 3001 1306 3003 2333 3066 3212 3008 2302 3010 3011
4 6666 8432 4011 1306
4
3011 3013
6666 2001
2004 3001
2222 6666
输出样例:
2
Go by the line of company #3 from 3011 to 3013.
10
Go by the line of company #4 from 6666 to 1306.
Go by the line of company #3 from 1306 to 2302.
Go by the line of company #2 from 2302 to 2001.
6
Go by the line of company #2 from 2004 to 1204.
Go by the line of company #1 from 1204 to 1306.
Go by the line of company #3 from 1306 to 3001.
Sorry, no line is available.

分析:【很简单的,别跑^_^】

一遍DFS即可~DFS过程中要维护两个变量:minCnt-中途经停的最少的站; minTransfer-需要换乘的最小次数~
0.可以这样计算出一条线路的换乘次数:在line[10000][10000]的数组中保存每两个相邻站中间的线路是几号线~从头到尾遍历最终保存的路径,preLine为前一小段的线路编号,如果当前的结点和前一个结点组成的这条路的线路编号和preLine不同,说明有一个换乘,就将cnt+1,最后遍历完累加的cnt即是换乘的次数~
1.可以这样计算出一条线路中途停站的次数:在dfs的时候有个变量cnt,表示当前路线是所需乘的第几个站,每次dfs时候将cnt+1表示向下遍历一层~cnt就是当前中途停站的次数~
2.可以这样输出结果:和计算线路换乘次数的思路一样,每当preLine和当前Line值不同的时候就输出一句话~保存preTransfer表示上一个换乘站,最后不要忘记输出preTransfer和最后一个站之间的路即使最后一个站并不是换乘站~ 

喵喵喵~

PAT 1131. Subway Map (30) -甲级(图的遍历,DFS)

In the big cities, the subway systems always look so complex to the visitors. To give you some sense, the following figure shows the map of Beijing subway. Now you are supposed to help people with your computer skills! Given the starting position of your user, your task is to find the quickest way to his/her destination.

Input Specification:

Each input file contains one test case. For each case, the first line contains a positive integer N (< =100), the number of subway lines. Then N lines follow, with the i-th (i = 1, …, N) line describes the i-th subway line in the format:

M S[1] S[2] … S[M]

where M (<= 100) is the number of stops, and S[i]’s (i = 1, … M) are the indices of the stations (the indices are 4-digit numbers from 0000 to 9999) along the line. It is guaranteed that the stations are given in the correct order — that is, the train travels between S[i] and S[i+1] (i = 1, …, M-1) without any stop.

Note: It is possible to have loops, but not self-loop (no train starts from S and stops at S without passing through another station). Each station interval belongs to a unique subway line. Although the lines may cross each other at some stations (so called “transfer stations”), no station can be the conjunction of more than 5 lines.

After the description of the subway, another positive integer K (<= 10) is given. Then K lines follow, each gives a query from your user: the two indices as the starting station and the destination, respectively.

The following figure shows the sample map.
Note: It is guaranteed that all the stations are reachable, and all the queries consist of legal station numbers.

Output Specification:

For each query, first print in a line the minimum number of stops. Then you are supposed to show the optimal path in a friendly format as the following:

Take Line#X1 from S1 to S2.
Take Line#X2 from S2 to S3.
……
where Xi’s are the line numbers and Si’s are the station indices. Note: Besides the starting and ending stations, only the transfer stations shall be printed.

If the quickest path is not unique, output the one with the minimum number of transfers, which is guaranteed to be unique.

Sample Input:

4
7 1001 3212 1003 1204 1005 1306 7797
9 9988 2333 1204 2006 2005 2004 2003 2302 2001
13 3011 3812 3013 3001 1306 3003 2333 3066 3212 3008 2302 3010 3011
4 6666 8432 4011 1306
3
3011 3013
6666 2001
2004 3001

Sample Output:

2
Take Line#3 from 3011 to 3013.
10
Take Line#4 from 6666 to 1306.
Take Line#3 from 1306 to 2302.
Take Line#2 from 2302 to 2001.
6
Take Line#2 from 2004 to 1204.
Take Line#1 from 1204 to 1306.
Take Line#3 from 1306 to 3001.

题目大意:找出一条路线,使得对任何给定的起点和终点,可以找出中途经停站最少的路线;如果经停站一样多,则取需要换乘线路次数最少的路线~
【很简单的,别跑^_^】
分析:一遍DFS即可~DFS过程中要维护两个变量:minCnt-中途经停的最少的站; minTransfer-需要换乘的最小次数~
0.可以这样计算出一条线路的换乘次数:在line[10000][10000]的数组中保存每两个相邻站中间的线路是几号线~从头到尾遍历最终保存的路径,preLine为前一小段的线路编号,如果当前的结点和前一个结点组成的这条路的线路编号和preLine不同,说明有一个换乘,就将cnt+1,最后遍历完累加的cnt即是换乘的次数~
update:由于新的PAT系统中会显示原解法有一个测试用例内存超限,考虑到line[10000][10000]存储的方式太暴力了,所以将line换成了unordered_map<int, int> line存储的方式,第一个int用来存储线路,每次将前四位存储第一个线路,后四位存储第二个线路,使用a[i-1]*10000+a[i]的方式存储,第二个int用来保存两个相邻中间的线路是几号线~
1.可以这样计算出一条线路中途停站的次数:在dfs的时候有个变量cnt,表示当前路线是所需乘的第几个站,每次dfs时候将cnt+1表示向下遍历一层~cnt就是当前中途停站的次数~
2.可以这样输出结果:和计算线路换乘次数的思路一样,每当preLine和当前Line值不同的时候就输出一句话~保存preTransfer表示上一个换乘站,最后不要忘记输出preTransfer和最后一个站之间的路即使最后一个站并不是换乘站~

喵呜~

PAT 1129. Recommendation System (25) 甲级

Recommendation system predicts the preference that a user would give to an item. Now you are asked to program a very simple recommendation system that rates the user’s preference by the number of times that an item has been accessed by this user.

Input Specification:

Each input file contains one test case. For each test case, the first line contains two positive integers: N (<= 50000), the total number of queries, and K (<= 10), the maximum number of recommendations the system must show to the user. Then given in the second line are the indices of items that the user is accessing — for the sake of simplicity, all the items are indexed from 1 to N. All the numbers in a line are separated by a space.

Output Specification:

For each case, process the queries one by one. Output the recommendations for each query in a line in the format:

query: rec[1] rec[2] … rec[K]

where query is the item that the user is accessing, and rec[i] (i = 1, … K) is the i-th item that the system recommends to the user. The first K items that have been accessed most frequently are supposed to be recommended in non-increasing order of their frequencies. If there is a tie, the items will be ordered by their indices in increasing order.

Note: there is no output for the first item since it is impossible to give any recommendation at the time. It is guaranteed to have the output for at least one query.

Sample Input:
12 3
3 5 7 5 5 3 2 1 8 3 8 12
Sample Output:
5: 3
7: 3 5
5: 3 5 7
5: 5 3 7
3: 5 3 7
2: 5 3 7
1: 5 3 2
8: 5 3 1
3: 5 3 1
8: 3 5 1
12: 3 5 8

题目大意:根据用户每次点击的东西的编号,输出他在点当前编号之前应该给这个用户推荐的商品的编号~只推荐k个~也就是输出用户曾经点击过的商品编号的最多的前k个~如果恰好两个商品有相同的点击次数,就输出编号较小的那个~
分析:【并不复杂~只是写的比较详细~不怕不怕~(摸头…】因为每个商品有两个属性:编号value和出现的次数cnt,编号具有唯一性,然后set又会根据大小自动排序,所以我们可以考虑将value和cnt组成一个node属性,把所有商品编号和它对应的次数变成node放入set里面,重载小于号,使<根据set中node的cnt排序,如果cnt相等就按照node的value排序~
这样set里面就是按照出现次数排序好的商品node,每次输出set的前k个node的value值就可以~(要记住,因为是点击前推荐,所以我们在接收完num的值后,应该先输出再插入让set帮忙排序当前num,当前的这个点击编号暂时先不算在输出结果里面的~)
首先在struct node里面重载<号,如果当前cnt不等于a.cnt就将cnt大的排在前,否则将value小的排在前面~
每次输入的时候,先不插入,先输出,当i != 0时候开始输出,因为i==0时候用户才第一次点击,没有可以推荐的~(沮丧脸…) 输出的同时记录输出过的个数tempCnt,当tempCnt < k的时候输出,因为只要前k个~所以就从头到尾依次输出set中的值就可以啦~
book[num]标记num出现的次数,每次寻找set中当前值为num和次数为book[num]的那个值,如果找到了就把他移除,(找到说明这个数已经出现过啦,cnt已经不对啦,先移除掉吧~)然后将book[num]+1,在将node(num, book[num])插入到set中,set会帮忙根据我们自定义的<的规则自动排序哒~

 

CCCC-GPLT L3-015. 球队“食物链” 团体程序设计天梯赛

某国的足球联赛中有N支参赛球队,编号从1至N。联赛采用主客场双循环赛制,参赛球队两两之间在双方主场各赛一场。
联赛战罢,结果已经尘埃落定。此时,联赛主席突发奇想,希望从中找出一条包含所有球队的“食物链”,来说明联赛的精彩程度。“食物链”为一个1至N的排列{ T1 T2 … TN },满足:球队T1战胜过球队T2,球队T2战胜过球队T3,……,球队T(N-1)战胜过球队TN,球队TN战胜过球队T1。
现在主席请你从联赛结果中找出“食物链”。若存在多条“食物链”,请找出字典序最小的。
注:排列{ a1 a2 …aN }在字典序上小于排列{ b1 b2 … bN },当且仅当存在整数K(1 <= K <= N),满足:aK < bK且对于任意小于K的正整数i,ai=bi。

输入格式:
输入第一行给出一个整数N(2 <= N <= 20),为参赛球队数。随后N行,每行N个字符,给出了NxN的联赛结果表,其中第i行第j列的字符为球队i在主场对阵球队j的比赛结果:“W”表示球队i战胜球队j,“L”表示球队i负于球队j,“D”表示两队打平,“-”表示无效(当i=j时)。输入中无多余空格。

输出格式:
按题目要求找到“食物链”T1 T2 … TN,将这N个数依次输出在一行上,数字间以1个空格分隔,行的首尾不得有多余空格。若不存在“食物链”,输出“No Solution”。

输入样例1:
5
-LWDW
W-LDW
WW-LW
DWW-W
DDLW-
输出样例1:
1 3 5 4 2
输入样例2:
5
-WDDW
D-DWL
DD-DW
DDW-D
DDDD-
输出样例2:
No Solution

分析:
0.既然是字典序最小的,而且必须包含所有的球队编号,那如果存在的话1肯定是结果数组的第一位~
1.接收数据:用v[21][21]存储比赛结果,如果是W就将v[i][j]置为1,表示i战胜过j,如果是L就将v[j][i]置为1,表示j战胜过i,其余的不用管~
2.dfs(int index, int num):index从1到n用来表示当前即将写入的结果数组result的下标,num表示当前的球队的编号,从1开始。
3.flag用来标记是否已经找到一个这样的结果数组,如果已经找到了(flag == 1)就return; 否则将当前下标index的result写入num值。
当index等于n的时候,并且v[num][1]等于true,表示已经写到了n个球员,而且这个球队num也曾经战胜过球队1~如果仅仅是index == n,就直接return不用继续向下找了~
4.cut标记剪枝,首先cut等于false,当所有没有访问过的结点中没有一个结点的v[i][1] == true,即没有一个球队战胜过1,就直接return,因为这条路径肯定找不到回路啦~
5.然后将num球队编号标记为已经访问过【visit[num] = true;】遍历num所有打败过的球队,并将index + 1,直到dfs结束的最后将visit标记回false
6.最后根据flag的值输出结果,如果flag为0说明没有满足题意的球队,就输出No Solution,如果flag = 1就输出result数组中保存的结果~

 

CCCC-GPLT L3-013. 非常弹的球 团体程序设计天梯赛

刚上高一的森森为了学好物理,买了一个“非常弹”的球。虽然说是非常弹的球,其实也就是一般的弹力球而已。森森玩了一会儿弹力球后突然想到,假如他在地上用力弹球,球最远能弹到多远去呢?他不太会,你能帮他解决吗?当然为了刚学习物理的森森,我们对环境做一些简化:

假设森森是一个质点,以森森为原点设立坐标轴,则森森位于(0, 0)点。
小球质量为w/100 千克(kg),重力加速度为9.8米/秒平方(m/s2)。
森森在地上用力弹球的过程可简化为球从(0, 0)点以某个森森选择的角度ang (0 < ang < pi/2) 向第一象限抛出,抛出时假设动能为1000 焦耳(J)。
小球在空中仅受重力作用,球纵坐标为0时可视作落地,落地时损失p%动能并反弹。
地面可视为刚体,忽略小球形状、空气阻力及摩擦阻力等。
森森为你准备的公式:

动能公式:E = m * v2 / 2
牛顿力学公式:F = m * a
重力:G = m * g
其中:
E – 动能,单位为“焦耳”
m – 质量,单位为“千克”
v – 速度,单位为“米/秒”
a – 加速度,单位为“米/秒平方”
g – 重力加速度
输入格式:

输入在一行中给出两个整数:1 <= w <= 1000 和 1 <= p <= 100,分别表示放大100倍的小球质量、以及损失动力的百分比p。

输出格式:

在一行输出最远的投掷距离,保留3位小数。

输入样例:
100 90
输出样例:
226.757

分析:
因为E=1/2mv^2,所以v^2=2E/m
当v分解为垂直方向的vsinθ和水平方向的vcosθ,所以水平方向的v为vsinθ,t为vcosθ/g,抛到最高点时通过的路程为s = vt = vsinθvcosθ/g,落下来同样相同的距离,s = 2vsinθvcosθ/g
因为2sinθvcosθ=sin2θ,sin2θ的最大值为1,即2θ=90°,θ=45°的时候s取得最大值~
这样s = v^2/g
又因为v^2=2E/m,在代码中v^2为变量v2,所以v2 = 2 * 1000 * 100 / w,即E = 1000, m = w/100
每次将v2/g 即v2 / 9.8的结果累加到s中,可以得到s为最后求得的总距离,每一次while循环,都要将v2损失百分比p,直到v2足够小(这里取0.000001可以通过所有测试用例,如果是0.00001会有一个测试点答案错误)的时候退出循环~

 

CCCC-GPLT L2-020. 功夫传人 团体程序设计天梯赛

一门武功能否传承久远并被发扬光大,是要看缘分的。一般来说,师傅传授给徒弟的武功总要打个折扣,于是越往后传,弟子们的功夫就越弱…… 直到某一支的某一代突然出现一个天分特别高的弟子(或者是吃到了灵丹、挖到了特别的秘笈),会将功夫的威力一下子放大N倍 —— 我们称这种弟子为“得道者”。
这里我们来考察某一位祖师爷门下的徒子徒孙家谱:假设家谱中的每个人只有1位师傅(除了祖师爷没有师傅);每位师傅可以带很多徒弟;并且假设辈分严格有序,即祖师爷这门武功的每个第i代传人只能在第i-1代传人中拜1个师傅。我们假设已知祖师爷的功力值为Z,每向下传承一代,就会减弱r%,除非某一代弟子得道。现给出师门谱系关系,要求你算出所有得道者的功力总值。

输入格式:
输入在第一行给出3个正整数,分别是:N(<=105)——整个师门的总人数(于是每个人从0到N-1编号,祖师爷的编号为0);Z——祖师爷的功力值(不一定是整数,但起码是正数);r ——每传一代功夫所打的折扣百分比值(不超过100的正数)。接下来有N行,第i行(i=0, …, N-1)描述编号为i的人所传的徒弟,格式为:

Ki ID[1] ID[2] … ID[Ki]

其中Ki是徒弟的个数,后面跟的是各位徒弟的编号,数字间以空格间隔。Ki为零表示这是一位得道者,这时后面跟的一个数字表示其武功被放大的倍数。

输出格式:
在一行中输出所有得道者的功力总值,只保留其整数部分。题目保证输入和正确的输出都不超过1010。

输入样例:
10 18.0 1.00
3 2 3 5
1 9
1 4
1 7
0 7
2 6 1
1 8
0 9
0 4
0 3
输出样例:
404

分析:一开始没弄懂题意,以为是是放大师傅的功力,原来是师傅功力减弱r%后的功力。。用二维数组v存储师门谱系关系,v[i]表示编号为i的师傅所拥有的徒弟,如果徒弟个数等于0,也就是说这是个得道者,那么v[i][0]保存放大的倍数,而且用visit[i] = true标记当前的这个编号的人是得道者~用深度优先搜索,每当遇到visit[index] = true也就是说这是个得道者的时候,就累加放大后的功力,power * v[index][0],累加到result中~遍历v[index]的所有弟子,并将功力减弱r%,也就是power * (1 – r/100),最后输出的是result的整数值(int)result ~~~