首页 > 代码库 > 解题报告

解题报告

1、Xxy 的车厢调度
(train.cpp/c/pas)
Description
                                                                                                                                                                                                    ,   技术分享

 


再从 B 方向驶出,同时它的车厢可以重新组合。假设
从 A 方向驶来的火车有 n 节(n<=1000) ,分别按照顺
序编号为 1,2,3,…,n。假定在进入车站前,每节
车厢之间都不是连着的,并且它们可以自行移动到 B
处的铁轨上。 另外假定车站 C 可以停放任意多节车厢。
但是一旦进入车站 C,它就不能再回到 A 方向的铁轨
上了,并且一旦当它进入 B 方向的铁轨,它就不能再
回到车站 C。
负责车厢调度的 xxy 需要知道能否使它以
a1,a2,…,an 的顺序从 B 方向驶出,请来判断能否得到
指定的车厢顺序。
Input
输入文件的第一行为一个整数 n,其中 n<=1000,表示有 n 节车厢,第二行为 n 个数字,表
示指定的车厢顺序。
Output
如果可以得到指定的车厢顺序,则输出一个字符串”YES”,否则输出”NO”(注意要大写,不
包含引号) 。还有,xxy 说了 这题 AC 有糖吃。
Example
train.in train.out
5
5 4 3 2 1
YES
Hint
对于 50%的数据,1<=N<=20。
对于 100%的数据,1<=N<=1000。

【思路】

模拟法做 B相当于是一个栈

如果站内没有当前行驶来的车,则将小于当前车的编号的车全部入栈(包括当前车)

再将这辆车驶出;若当前车在栈中直接将它驶出。否则无解。

(注意输出大小写。。。吃亏了。。。)

【代码】

技术分享
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 using namespace std;
 5 const int maxx=1001;
 6 int a[maxx];
 7 int stack[maxx];
 8 int main()
 9 {
10 //    freopen("train.in","r",stdin);
11 //    freopen("train.out","w",stdout);
12     int n;
13     scanf("%d",&n);
14     for(int i=1;i<=n;i++)
15     scanf("%d",&a[i]);
16     int cur=1;
17     int top=0;
18     for(int i=1;i<=n;i++)
19     {
20         while(cur<=a[i])
21         stack[++top]=cur++;
22         if(stack[top]==a[i])
23         --top;
24         else
25         {
26                 printf("NO");
27                 return 0;
28         }
29     
30     }
31     printf("YES");
32 //    fclose(sdtin);
33 //    fclose(stdout);
34     return 0;
35 }
View Code

2、迷 宫

(maze.cpp/c/pas)
Description
Karles 和朋友到迷宫玩耍,没想到遇上了 10000000 年一次的大洪水,好在 Karles 是一个喜
欢思考的人,他发现迷宫的地形和洪水有如下性质:
①迷宫可以被看做是一个 N*M 的矩形方阵,其中左上角坐标为(1,1),右下角坐标为(n,m),
每个格子(i,j)都有一个高度 h(i,j)。
②洪水从(sx,sy)开始,如果一个格子被洪水淹没,那这个格子四周比它低(或相同)的格子
也会被淹没。
现在 Karles 想请你帮忙算算,有多少个格子不会被淹没,以及 Karles 想问一下格子(x,y)是否
被淹没,如果被淹没的话就输出”Yes”,否则输出”No”。
Input
第一行包含两个整数 n,m。
以下 n 行,每行 m 个数,第 i 行第 j 个数表示格子高度 h(i,j)。
下面一行包含两个整数 sx,sy,表示最初被洪水淹没的格子。
下面一行包含一个整数 q,表示询问的数量。
最后 q 行每行包含两个整数 x,y,表示询问的格子。
Output
输出的第一行,为永远不会被淹没的格子的数量。
以下 q 行,为格子被淹没的情况,输出”Yes”或者”No”(不包含引号)
Example
maze.in maze.out
3 3
1 2 3
2 3 4
3 4 5
2 2
2
1 2
2 3
5
Yes
No
Hint
对于 10%的数据,(sx,sy)为迷宫内的最高点。
对于 30%的数据,1<=N,M<=5,q=1。
对于 60%的数据,1<=N,M<=100,q<=100。
对于 100%的数据,1<=N,M<=2000,q<=1000。

【思路】广搜 相当于细胞搜索;

从被洪水淹没的格子开始搜素(方向为上下左右),如果海拔小于等于当前格子则入队,并做好标记表示已经被淹了,

入队的条件为 没有出界,海拔小于等于当前搜索的海拔 并且没有被淹(即还没有做标记)!!!(经常忘记)

直到队列元素为空 ,全部都扫一遍,没有打标记的就是没有淹的;

(还是要注意输出大小写。。。)

【代码】

技术分享
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 using namespace std;
 5 const int maxx=2001;
 6 int mmap[maxx][maxx];
 7 int dx[4]={0,1,-1,0},
 8     dy[4]={1,0,0,-1};
 9 bool vis[maxx][maxx];
10 int qque[maxx][maxx];
11 int n,m;
12 void bfs(int x,int y)
13 {
14     vis[x][y]=1;
15     int head=0,t=1;
16     qque[1][1]=x;
17     qque[1][2]=y;
18     do
19     {
20         head++;
21         for(int i=0;i<=3;i++)
22         {
23             int xx=qque[head][1]+dx[i];
24             int yy=qque[head][2]+dy[i];
25             if(xx>=1&&xx<=n&&yy>=1&&yy<=m&&mmap[xx][yy]<=mmap[qque[head][1]][qque[head][2]]&&!vis[xx][yy])
26             {
27                 vis[xx][yy]=1;
28                 t++;
29                 qque[t][1]=xx;
30                 qque[t][2]=yy;
31             }
32         }
33     }while(head<=t);
34 }
35 int main()
36 {
37     //freopen("maze.in","r",stdin);
38     //freopen("maze.out","w",stdout);
39     scanf("%d%d",&n,&m);
40     for(int i=1;i<=n;i++)
41     for(int j=1;j<=m;j++)
42     scanf("%d",&mmap[i][j]);
43     int x,y;
44     scanf("%d%d",&x,&y);
45    bfs(x,y);
46     int sum=0;
47     for(int i=1;i<=n;i++)
48     for(int j=1;j<=m;j++)
49     {
50         if(!vis[i][j])
51         sum++;
52     }
53     printf("%d\n",sum);
54     int t;
55     scanf("%d",&t);
56     int i,j;
57     while(t--)
58     {
59         scanf("%d%d",&i,&j);
60         if(vis[i][j])
61         printf("No\n");
62         else
63         printf("Yes\n");
64     }
65 //    fclose(stdin);
66 //    fclose(stdout);
67     return 0;
68 }
View Code

3.发 零 食

(dropping.cpp/c/pas)
Description
HKD 看学弟学妹们学习辛苦,决定给发零食吃
HKD 是土豪,所以他决定买零食的时候,从 1 块钱的开始买,然后买 2 块钱的,然后 3 块钱
的,……,直至 D 块钱的。而且 k 块钱的零食买 2^(k-1)个。
但 HKD 从来不吃零食,所以他不知道他买的零食是否好吃。
于是他把所有零食编号,怎么编呢?
对于价钱为 k 的零食,从 1 开始编,然后 2,3,编到 2^(k-1)
例:1 块钱的:1
2 块钱的:1 2
3 块钱的:1 2 3 4
学编程的基本功是搜索嘛
为了考验学弟学妹们的搜索能力
HKD 把所有零食掺杂在了一起,送到学弟学妹们的面前(送货上门,真好)
他规定:
1、只能排队一个一个开始搜
2、所有人最终只能吃 1 个零食
3、所有人只能吃最贵的零食
4、 所有人搜索零食的时候, 只能从 1 块钱的开始搜, 然后搜 2 块钱的, 然后搜 3 块钱的……,
直到最贵的
5、初始时认为所有零食都是好吃的
6、 为了增加难度, HKD 制定了新规定: 若一个人搜到的第 i 块钱的编号为 j 的零食是好吃的,
那么他就把这个零食更改为不好吃,然后去搜第 i+1 块钱的编号为 j*2-1 的零食。若一个人
搜到的第 i 块钱的编号为 j 的零食是不好吃的,那么他就把这个零食更改为好吃,然后去搜
第 i+1 块钱的编号为 j*2 的零食
注:若 n 个人都最后搜到了同一个零食,那么他们就分享一个吧
然而不知道为啥,HKD 想知道最后一个人吃的是编号为几的零食
那就麻烦最后一个人告诉他吧
注:若其中有一个人无法搜到最贵的零食,就告诉他-1
Input
第一行输入测试点编号
下一行输入 T,表示有 T 组数据
接下来 T 行,每行输入 2 个数输入 D 和学弟学妹的人数 M
Output
对于每组测试数据
输出一行 k : ans,表示第 k 组数据的答案为 ans
冒号与每个数字之间空 1 格
每 2 组数据之间空一行
Example
dropping.in dropping.out
1
6
4 2
3 4
10 1
2 2
8 128
1 : 12
2 : 7
3 : 512
4 : 3
5 : 255
Hint
测试点编号
T D
1、2
<=1 <=10
3、4、5
<=20 <=25
6、7、8、9
<=700 <=30
10 <=1 <=1
学弟学妹人数 M <2^31 且不超过 D 块钱的零食个数。

【思路】:由题目描述可知,这是一棵完全二叉树;

每一层为 2的层次方-1;从第一层的第一个结点开始,到每一个结点的条件是好吃与不好吃;

最后一定会出界,出界时跳出;将刚出界点的编号/2,就是出界之前的点;即为最贵的零食;

:结点k的左右子结点的标号为2*看,2*k+1;

之前没想到是因为不理解题意;而且没有敏感的认识到2^k-1为完全二叉树每层的结点数

状态改变 循环+取反 边界:为出界即超过最贵的零食的那一层;

学到的  1<<Max     为2^max‘

【代码】

技术分享
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 using namespace std;
 5 const int maxx=20;
 6 int s[1<<maxx];//为2的maxx次方,因为最大结点数为2的maxx-1; 
 7 int main()
 8 {
 9     int n,k=1;
10     scanf("%d",&n);//测试点 
11     int t;
12     scanf("%d",&t);//t组测试数据 
13     while(t--)
14     {
15         int d,I;//钱和同学 
16         scanf("%d%d",&d,&I);
17         int n=(1<<d)-1;//n为最大结点的标号 
18         memset(s,0,sizeof(s));//好吃与不好吃 
19         for(int i=0;i<I;i++)//从第一个同学开始搜 
20         {
21              k=1;//从1块钱开始搜 
22             for(;;)
23             {
24                 s[k]=!s[k];//状态变成相反 
25                 k=s[k]?k*2:k*2+1;//去哪个零食 
26                 if(k>n)break;//已经出界了跳出 
27             }
28         }
29         printf("%d\n",k/2);//出界之后/2就是这个结点的爸爸 
30     }
31     return 0;
32 }
View Code

 

解题报告