2013 计算机院
A. 日期
时间限制 1000 ms 内存限制 65536 KB题目描述请你计算出第 X 年 Y 月 Z 日是第 X 年的第几天。其中, 1 月 1 日是第一天, 1 月 2 日是第二天,以此类推。计算时请注意闰年的影响。对于非整百年,年数能整除 4 是闰年,否则不是闰年;对于整百年,年数能整除 400 是闰年,否则不是闰年。如 1900 年和 1901 年不是闰年,而 2000 年和 2004 年是闰年。输入格式第一行有一个整数 T ( T ≤100) ,表示一共有 T 组数据需要你处理。接下来一共有 T 行,每行是一个如下格式的字符串: X : Y : Z ,表示你需要计算第 X 年 Y 月 Z日是第 X 年的第几天。其中 X 是一个大于 0 ,小于 2100 的整数。保证字符串的格式都是合法的,字符串所表示的日期也都是存在的。输出格式对于每组数据,你需要输出一个整数,表示所求得的结果。输入样例22013:4:12112:4:12输出样例102103
1、思路
(1)输入格式纠结半天,想着怎么才能从string字符串中分离出年月日…最后看佬们的解答发现直接scanf就可以…学到后面忘了前面栓q,如果因为这种原因没做出来真的会想紫砂;
(2)其他地方和王道上的题目一样,注意平年闰年日期的预处理和判断闰年的函数。
2、代码
# include<cstdio>
# include<iostream>
using namespace std;
int daytab[2][13]= {
{0,31,28,31,30, 31,30,31,31, 30,31,30,31},
{0,31,29,31,30, 31,30,31,31, 30,31,30,31}
};
bool IsYeapYear(int year) {
return (year%4==0&&year%100!=0) || year%400==0;
}
int main() {
int t;
cin >> t;
while(t--) {
int year,month,day;
scanf("%d:%d:%d",&year,&month,&day); // 以后该记住了吧orz
int res = 0;
int row = IsYeapYear(year);
for(int i = 0; i < month ; i++) {
res += daytab[row][i];
}
res += day;
cout << res <<endl;
}
return 0;
}
B.
统计节点个数
题目描述给出一棵有向树,一共有 N (1< N ≤1000) 个节点,如果一个节点的度(入度 + 出度)不小于它所有儿子以及它父亲的度 ( 如果存在父亲或儿子 ) ,那么我们称这个节点为 p 节点,现在你的任务是统计 p 节点的个数。如样例,第一组的 p 节点为 1,2,3 ;第二组的 p 节点为 0 。输入格式第一行为数据组数 T (1≤ T ≤100) 。每组数据第一行为 N 表示树的节点数。后面为 N −1 行,每行两个数 x , y (0≤ x , y < N ) ,代表 y是 x 的儿子节点。输出格式每组数据输出一行,为一个整数,代表这棵树上 p 节点的个数。输入样例250 11 22 33 430 20 1输出样例31
1、思路:
(1)题目要求计算的度为入度和出度的和,度是图中的概念,用邻接矩阵计算最为方便。且又因为在该题中箭头的方向不是关键(因为是入度+出度),可以直接将有向树转换为无向图。
(2)遍历节点i是否是p节点的时候,可以先假设是p节点,只要i的度数<相邻节点的度数,就说明不是p节点,跳出本次循环。
2、代码:
#include <iostream>
#include <cstdio>
#include <stack>
#include <string.h>
using namespace std;
const int N = 1005;
int adjMatrix[N][N]; // 邻接矩阵记录两个节点之间是否有边
int degree[N]; // 记录节点度数
int main()
{
int t;
cin >> t;
while(t--) {
int n;
cin >> n;
memset(adjMatrix,0,sizeof(adjMatrix));
memset(degree,0,sizeof(degree));
for(int i = 0 ; i < n - 1 ; i++) {
int x,y;
cin >> x >> y; // y是x的儿子
adjMatrix[x][y] = 1;
adjMatrix[y][x] = 1;
degree[x]++;
degree[y]++;
}
int cnt_p = 0;
for(int i = 0 ; i < n ; i++) { // 按行遍历
bool flag = true; // 假设是p节点
for(int j = 0 ; j < n ; j++) {
if(adjMatrix[i][j] == 1) {
if(degree[i] < degree[j]) { // 如果i的度数 < 相邻j的度数
flag = false; // 不是p节点
break;
}
}
}
if(flag) cnt_p++;
}
cout << cnt_p << endl;
}
return 0;
}
C.中序遍历序列
题目描述给出一个序列,判断该序列是不是某二叉搜索树的中序遍历序列,如果是输出 "Yes" ,否则输出 "No" 。一颗带权二叉树是一颗二叉搜索树(二叉排序树),当且仅当对于任意一个节点,他的左子树中的所有权值小于当前节点的权值,且它的右子树中的所有权值均大于当前节点的权值。输入格式第一行 T ( T ≤10) 代表数据组数。每组数据包括两行: 第一行为一个整数 N (1≤ N ≤400), 表示序列的长度。第二行包含 N 个整数,表示这个这个序列,序列中的数的 x 范围为 (1≤ x ≤100000) 。输出格式每组数据,如果是二叉搜索树的中序遍历序列输出 "Yes", 否则输出 "No" 。输入样例241 2 3 441 3 2 4输出样例YesNo
2014 计算机院
Problem A. 中位数
题目描述给定一个长度为 N 的非降数列,求数列的中位数。中位数:当有序数列的项数 N 为奇数时,处于中间位置的变量即为中位数;当 N 为偶数时,中位数则为处于中间位置的两个数的平均数。输入格式输入数据第一行是一个整数 T ( 1<=T<=100 ),表示测试数据的组数。对于每组测试数据:第一行是一个正整数 N ( 1<=N<=100 ),表示数列长度。第二行有 N 个整数,整数之间用空格隔开,所有的整数都不超过 100000 ,表示这个数列的元素。输出格式对于每组测试数据,输出数列的中位数,请不要输出小数点末尾多余的 0 。输入样例241 1 2 251 1 2 2 3输出样例1.52
主要是输出格式的问题,题目要求小数末尾的0不要输出,找了半天发现cout默认不输出末尾0 。
Problem B. 内存分配
题目描述在操作系统中,内存分配是非常重要的工作。已知内存空间由 N 个内存块组成,这些内存块从 1 到 N 编号,进行内存分配时,操作系统将选择一块大小足够的内存全部分配给请求内存的进程。例如,当进程请求 10MB 的内存时,操作系统必须向该进程分配一个不小于 10MB 的内存块。内存块不能被重复分配。操作系统有三种基本的分配方式,分别为:首次适应:从 1 号到 N 号内存块依次查找,直到找到第一块足够大的且未分配出去的内存块,将其分配给进程。最佳适应:找到当前未分配出去且大小足够的内存块中最小的内存块分配给进程。最差适应:找到当前未分配出去且大小足够的内存块中最大的内存块分配给进程。其中,最佳适应是应用最为广泛的分配方式。现在,操作系统要依次处理 M 个进程的内存请求,请按照最佳适应方式分配内存,并输出相应分配到的内存块的大小。如果没有大小足够的内存块可以满足当前请求,则输出 “NULL” (不包含引号),并跳出该请求。输入格式输入数据的第一行是测试数据组数 T ( T<=50 )每组数据由 4 行构成:第一行为一个整数 N ( 1<=N<=100 ),表示有 N 个内存块。第二行有 N 个整数,第 i 个整数表示第 i 块内存块的大小。第三行为一个整数 M ( 1<=M<=100 ),表示有 M 个请求。第四行有 M 个整数,表示进程所请求的内存空间。输出格式每组数据输出一行,每行有 M 个数,表示操作系统采用最佳适应方式,依次分配给进程的内存块大小;如果没有可用的内存块,输出 “NULL” (不包含引号)请不要输出多余的行尾空格,否则会被判为格式错误。输入样例247 5 10 324 643 5 9 1035 12 6输出样例5 75 NULL 9
1、思路:题目看着挺长,其实不难,用结构体排序做的,注意一下输出结尾不能有多余空格。
2、代码
#include<cstdio>
#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;
struct Block {
int id;
int len;
int flag; // 1:空闲,0:已被分配
};
// 按内存块大小升序排列
bool cmp(Block x,Block y) {
return x.len < y.len;
}
int main() {
int t;
scanf("%d\n",&t);
while(t--) {
int n,m; // 内存块数、请求个数
cin >> n;
Block block[n+1]; // 存储内存块,注意内存块序号从1开始到n
for(int i = 1 ; i <= n ; i++) {
cin >> block[i].len;
block[i].id = i;
block[i].flag = 1;
}
sort(block, block + n,cmp);
cin >> m;
int req[m]; // 请求的内存空间
for(int i = 0 ; i < m ; i++) {
cin >> req[i];
}
for(int i = 0 ; i < m ; i++) {
bool find = false; // 找到可分配内存块的标准
for(int j = 1 ; j <= n ; j++) {
if(block[j].flag == 1 && block[j].len >= req[i]) {
find = true;
block[j].flag = 0;
cout << block[j].len;
break;
}
}
if(!find) cout << "NULL";
if(i = m - 1)
cout << endl;
else
cout << " ";
}
}
return 0;
}
Problem C. 图像识别
考的DFS…没时间看了
2014 软件院
Problem A. 奇偶求和
题目描述:给定 N 个数,分别求出这 N 个数中奇数的和以及偶数的和。输入格式第一行为测试数据的组数 T(1<=T<=50)。请注意,任意两组测试数据之间是相互独立的。每组数据包含两行:第一行为一个整数 N(1<=N<=10C)。 第二行为 N 个正整数,整数之间用一个空格隔开,且每个整数的绝对值均大不于 10^5。输出格式:每组数据输出两个数,即 N 个数中奇数之和和偶数之和,中间用空格隔开。输入样例251 2 3 4 551 1 1 1 1输出样例9 65 0
感觉软院是确实要简单一点,不知道合并以后的难度怎么样orz。
Problem B. 最长连续等差子数列
题目描述给定一个长度为 N 的整数数列,你需要在其中找到最长的连续子数列的长度,并满足这个子序列是等差的。注意公差小于或等于 0 的情况也是允许的。输入格式第一行为数据组数 T(1<=T<=100),表示测试数据的组数。对于每行测试数据:第一行是一个正整数 N(1<=N<=100),表示给定数列的长度。第二行是 N 个整数,其中第 i 个整数 valuei(1<=valuei<=10^5)表示下标为 i 的数字。输出格式对于每组测试数据,输出最长的连续等差子数列的长度。输入样例221 351 6 4 2 4输出样例23样例解释两组样例的最长连续等差子数列分别是{1,3}和{6,4,2}
感觉考的动态规划,也来不及看了…
Problem C. 最近公共祖先
题目描述给出一棵有 N 个节点的有根树 TREE(根的编号为 1),对于每组查询,请输出树上节点 u 和v 的最近公共祖先。最近公共祖先:对于有向树 TREE 的两个结点 u,v。最近公共祖先 LCA(TREE u,v)表示一个节点 x,满足 x 是 u、v 的祖先且 x 的深度尽可能大。输入格式输入数据第一行是一个整数 T(1<=T<=100),表示测试数据的组数。对于每组测试数据: 第一行是一个正整数 N(1<=N<=100),表示树上有 N 个节点。接下来 N-1 行,每行两个整数 u,v(1<=u,v<=N),表示节点 u 是 v 的父节点。接下来一行是一个整数 M(1<=M<=1000),表示查询的数量。接下来 M 行,每行两个整数 u,v(11<=u,v<=N),表示查询节点 u 和节点 v 的最近公共祖先。输出格式对于每个查询,输出一个整数,表示最近公共祖先的编号输入样例231 21 312 341 21 33 422 33 4113