主题:[讨论]第八次编程比赛题目
林木
[专家分:130] 发布于 2005-12-24 07:56:00
严重道歉,各位,我来晚了.比赛时间延长150分钟.
/////////////////////////////////////////////////////////////////////////////////
[color=FF0000]注意:不得不再提醒大家一下,你们的排名不仅将同你的正确率有关,另一个重要因素是效率,所以请在保证正确的情况下,尽量提高你的时空效率.[/color]
/////////////////////////////////////////////////////////////////////////////////
1.注释提取器
[题目描述]
给出一个程序源代码
要求输出其注释部分内容.即/* 与 */中的内容
[输入样例]
#include <stdio.h>/* Hello world*/
int main(){
printf("example.");/* 世界,你好. */
return 0;
}
[输出样例]:
Hello world 世界,你好.
提示:包括空格.
2.单词查找树(TRIE)
[题目描述]
在进行文法分析的时候,通常需要检测一个单词是否在我们的单词列表里。为了提高查找和定位的速度,通常都要画出与单词列表所对应的单词查找树,其特点如下:
根节点不包含字母,除根节点外每一个节点都仅包含一个大写英文字母;
从根节点到某一节点,路径上经过的字母依次连起来所构成的字母序列,称为该节点对应的单词。单词列表中的每个词,都是该单词查找树某个节点所对应的单词;
在满足上述条件下,该单词查找树的节点数最少。
例:
对一个确定的单词列表,请统计对应的单词查找树的节点数(包括根节点)
[输入样例]
注:为一个单词列表,每一行仅包含一个单词和一个换行/回车符。每个单词仅由大写的英文字符组成,长度不超过63个字符。文件总长度不超过32K,至少有一行数据.
A
AN
ASP
AS
ASC
ASCII
BAS
BASIC
[输出样例]
注:该文件中仅包含一个整数和一个换行/回车符。该整数为单词列表对应的单词查找树的节点数。
13
4.墙上的灯
[题目描述]:
Arthur King的城堡有一个圆形的大厅。大厅的墙壁上有N盏灯,分别按顺序从1到N编号。每盏灯都可以每打开或关上。在每一秒钟,如果第I+1盏灯是亮的,那么第I盏灯在下一秒会变化它的状态;特别的,如果第1盏灯是亮的,那么第N盏灯在下一秒会变化它的状态。
Arthur King给你某一时刻所有灯的状态,希望你能求出它们在M秒之后的状态。你正好想加入圆桌骑士的行列,赶快抓住这个机会,向Arthur King证明你的实力吧。
[输入描述]:
输入文件有N+1行。第一行有两个数N,M。此后N行,每行是一个数,不是0就是1。第I+1行的数描述初始时第I盏灯的状态。如果这个数为0,表示第I盏灯是灭的;如果这个数为1,表示第I盏灯是亮的。
20<N<500,2<M<200000
[输出描述]:
输出文件有N行,每行一个数,不是0就是1。第I行的数描述M秒后第I盏灯的状态。如果这个数为0,表示第I盏灯是灭的;如果这个数为1,表示第I盏灯是亮的。
[输入范例]:
3 1
0
0
1
[输出范例]:
0
1
1
4.强强的烦恼
[题目描述]:
新的赛季即将来临,强强将派出自己的球队---强强队 去参加这来之不易的比赛,由于这场比赛非常重要,强强 不光要考虑队员的体力和技术 还必须考虑到整个球队队员的亲密程度,如果球队中出现一些亲密度较差的队员那么一定会影响这个比赛的成绩,这个问题使强强很伤脑筋,因为他训练的队员太多了,无法完全掌握所有队员之间的亲密度~~。再这样下去强强精神就要崩溃了,看来我们还是要想个办法帮帮他。
你设计了一个程序,由程序存入各个球员之间的信息,用来方便强强查询。
输入数据:第一行3个数N,M,K 表示有N个队员M个关系以及K次询问(1<N<=2000,1<=M<=500000,1<=K<=500000)
接下来M+K行 ,前M行给出A,B(A<>B A B分别表示不同的两个队员的球衣编号A<=2000 B<=2000)两队员的关系(F表示亲密度较高 E表示亲密度较低) 后K行为强强的询问
值得注意的是:如果A与B亲密度比较低 B与C亲密度也比较低 那么A与C的亲密度就算为比较高咯
如果A与B亲密度比较高 B与C亲密度也比较高 那么A与C的亲密度就算为比较高咯
[输入样例]:
5 4 4
1 2 F
2 3 F
1 4 E
4 5 E
1 5
1 3
2 4
2 5
[输出样例]注:输出K行 如果询问的对象亲密度比较高则输出 高 如果亲密度比较低则输出 低 如果不清楚询问对象的关系那么就输出 不知道
例:
高
高
不知道
高
回复列表 (共35个回复)
21 楼
iAkiak [专家分:8460] 发布于 2005-12-23 22:56:00
// 4
#include <stdio.h>
char map[2000][2000] = {0};
int main()
{
int n, m, k, change, t, i, j, a, b;
char r[2];
scanf("%d%d%d",&n, &m, &k);
for (i = 0; i < m; i++)
{
scanf("%d%d%s", &a, &b, r);
a--, b--;
if (r[0] == 'F')
map[a][b] = map[b][a] = 1;
else
map[a][b] = map[b][a] = 2;
}
do
{
change = 0;
for (i = 0; i < n; i++)
{
for (j = i + 1; j < n; j++)
{
if (map[i][j] != 0)
continue;
for (t = 0; t < n; t++)
{
if (t != i && t != j && (map[i][t] == 1 || map[i][t] == 2) && map[i][t] == map[t][j])
{
map[j][i] = map[i][j] = 1;
change = 1;
break;
}
}
}
}
} while(change);
for (i = 0; i < k; i++)
{
scanf("%d%d", &a, &b);
a--, b--;
if (map[a][b] == 1)
printf("高\n");
else if (map[a][b] == 2)
printf("低\n");
else
printf("不知道\n");
}
return 0;
}
22 楼
FancyMouse [专家分:13680] 发布于 2005-12-24 12:35:00
第二题不就是NOI2001的题嘛……好没创意的说~
23 楼
林木 [专家分:130] 发布于 2005-12-24 13:15:00
@22,FancyMouse
..呵呵....
有原创题也有原题.旧的东西但很经典.
24 楼
mroske [专家分:1340] 发布于 2005-12-24 13:49:00
/*1*/
#include <stdio.h>
const unsigned short FIRST = '*/';
const unsigned short SECOND = '/*';
union Word {
unsigned short wWord;
struct TwoChar {
char chFirst;
char chSecond;
} toChar;
};
bool OutputComments(char* fileName)
{
Word word;
FILE* file;
size_t count = 0;
char chTemp;
if (file = fopen(fileName, "rt"))
{
while (count = fread((void*)&word, 2, 1, file)) {
if (word.wWord == FIRST) {
word.wWord = 0;
while (fread((void*)&word, 2, 1, file) && word.wWord != SECOND) {
putchar(word.toChar.chFirst);
word.wWord = 0;
fseek(file, -1, SEEK_CUR);
}
}
else if (word.toChar.chFirst == '\"') { // 处理字符串里的 "/* */"
fseek(file, -1, SEEK_CUR);
chTemp = word.toChar.chSecond;
while (chTemp != EOF && chTemp != '\"') {
chTemp = fgetc(file);
}
}
else
fseek(file, -1, SEEK_CUR);
}
fclose(file);
return true;
}
return false;
}
int _tmain(int argc, _TCHAR* argv[])
{
OutputComments("readme.txt");
system("pause");
return 0;
}
/*2*/
/*3*/
/*4*/
25 楼
FancyMouse [专家分:13680] 发布于 2005-12-24 19:00:00
我只是想说,那题的解题报告已经泛滥得不能再泛滥了。再出这种题的话貌似有点不妥~
26 楼
林木 [专家分:130] 发布于 2005-12-24 22:36:00
@fancymouse,25
呵呵,比赛就是为了提高。
1。如果为了这次比赛有人去看了解题报告,这也不定是件好事嘛。。。(至少他要改改嘛)
2。各位参加比赛的觉悟还是比较高的。
27 楼
goal00001111 [专家分:4030] 发布于 2005-12-25 09:47:00
/*1.注释提取器
[题目描述]
给出一个程序源代码
要求输出其注释部分内容.即/* 与 *///中的内容
/*[输入样例]
#include <stdio.h>/* Hello world*/
/* int main(){
printf("example.");/* 世界,你好. */
/* return 0;
}
[输出样例]:
Hello world 世界,你好.
提示:包括空格.
*/
/*算法思路:先读取文件9文本文件或二进制文件)到字符串中,然后对字符串进行分析。遍历字符串,查找第一个出现的'"' 或'/*’。如果先找到 '"',则从它起到下一个'"'之间的字符都不是注释;如果先找到'/*’,则从它起到下一个'/*’之间的字符都是注释,输出这些注释;继续查找,直到分析完整个字符串。
注意:在测试时请先在当前目录建立一个名为"ppp.txt"的文本文件或为"ppp.cpp"的二进制文件*/
/* 2005-12-24 梁见斌 */
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define SIZE 2000
void Solve(const char data[], int len); //处理字符串并输出注释
int main( void )
{
char buf[SIZE]; //用来直接存储从文件中读取的文件,每次只能读取一行
char data[SIZE]; //用来存储从文件中读取的所有文件
FILE *fp;
int count, k=0;
if((fp = fopen("ppp.cpp","rb")) == NULL) //读取二进制文件;或fopen("ppp.txt","r")读取文本文件
{
fprintf(stderr,"\nError opening file.\n");
exit(1);
}
while((!feof(fp))&&(k<SIZE)) //直到文件结束或者存储空间被占满
{
fgets(buf, SIZE, fp); //从文件中读取数据到数组buf
count = 0;
while(buf[count] != '\0') //把数组buf的元素复制到data中
{
data[k++] = buf[count++];
}
data[k] = '\0';
}
fclose(fp);
Solve(data, k); //处理字符串并输出注释
system("pause");
return 0;
}
void Solve(const char data[], int len)//处理字符串并输出注释
{
int flag, i, j;
for(i=0; i<len; i++)
{
if((data[i]=='"')||(data[i]=='/')&&(data[i+1]=='*'))//寻找特殊标志'"'和'/*’
{
if(data[i]=='"')//如果是先找到'"',其后直到下一个'"'之间的字符肯定不是注释
{
i++;
while((data[i]!='"')&&(i<len))
i++;
}
else //如果是先找到'/*’
{
i += 2;
flag = i; //记下此时i的位置
a:
while((data[i]!='*')&&(i<len))//一直往后,直到下一个'*'
i++;
if((data[++i]=='/')&&(i<len)) //判断'*'之后是否为'/',如果是,则从flag到i-2间的字符为注释
{
for(j=flag; j<i-1; j++) //打印注释
putchar(data[j]);
}
else if(i<len)//否则继续寻找'*/'
goto a;
}
}
}
}
28 楼
goal00001111 [专家分:4030] 发布于 2005-12-25 09:48:00
2.
/*算法介绍:
建立一个二杈树来表示树,左子树代表其后代,右子树代表其兄弟。每读入一个数据即进行处理(也可以
先读入全部数据,再一个个处理)把数据存入字符串str[],输入空行结束 。先单独处理第一个单词,
把它的字母依次存入二杈树,前后单词之间的关系为父子关系。之后依次处理后面的单词,
指针p指向根结点的左子树,若单词的第一个字母与p的数据相同,则分析p的左子树;若无左子树,
则创建一棵,把其他字母存入左子树。若单词的第一个字母与p的数据不相同,则分析p的右子树;
若无右子树,则创建一棵,把其他单词存入右子树。依此类推,直到输入结束。最后输出二杈树的所有结点 */
/* 2005-12-24 梁见斌 */
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct bnode
{
char data;
struct bnode *lchild, *rchild;
} btree;
void Solve(const char str[], btree *p);
btree* Save(const char str[], int n, btree *b);//把其余依次存入左子树
int nodes(btree *b);//输出二杈树的所有结点
int main(void)
{
btree *bt=NULL, *p;
char str[65];
int number;
gets(str); //读取数据,输入空行结束
if(str[0] != '\0')
{
bt = (btree*)malloc(sizeof(btree));//创建根结点
if(bt == NULL)
{
puts("It's wrong!");
return 1;
}
bt->lchild = bt->rchild = NULL;
bt = Save(str, 0, bt); //先存储第一个字符串
do
{
p = bt->lchild;
gets(str); //读取数据,输入空行结束
Solve(str, p);
} while(str[0] != '\0');
}
number = nodes(bt);
printf("%d\n", number);
system("pause");
return 0;
}
void Solve(const char str[], btree *p)
{
btree *s;
int i = 0;
while(str[i] != '\0') //依次判断字符串中的元素
{
if(str[i] == p->data) //如果和当前结点数据相同,判断该结点是否存在左子树
{
if(p->lchild != NULL) //若存在左子树 ,分析左子树
{
p = p->lchild;
i++;
}
else //否则把剩下的字符存储在右子树中
{
s = (btree*)malloc(sizeof(btree));
if(s == NULL)
{
puts("It's wrong!");
exit(1);
}
s->data = str[++i];
s->lchild = s->rchild = NULL;;
p->lchild = s;
p = Save(str, i+1, s); //把其余依次存入左子树,并结束数据的分析
break;
}
}
else if(p->rchild != NULL)
p = p->rchild;
else
{
s = (btree*)malloc(sizeof(btree));
if(s == NULL)
{
puts("It's wrong!");
exit(1);
}
s->data = str[i++];
s->lchild = s->rchild = NULL;;
p->rchild = s;
p = Save(str, i, s); //把其余依次存入左子树,并结束数据的分析
break;
}
}
}
btree* Save(const char str[], int n, btree *b)//把其余依次存入左子树
{
btree *p=b, *s;
while(str[n] != '\0')
{
s = (btree*)malloc(sizeof(btree));
if(s == NULL)
{
puts("It's wrong!");
exit(1);
}
s->data = str[n++];
s->lchild = s->rchild = NULL;;
p->lchild = s;
p = s;
}
return b;
}
int nodes(btree *b) //计算二杈树的所有结点
{
int num1, num2;
if(b==NULL)
return 0;
num1 = nodes(b->lchild);
num2 = nodes(b->rchild);
return (num1+num2+1);
}
29 楼
goal00001111 [专家分:4030] 发布于 2005-12-25 09:49:00
3.
/*算法思路:题目要求根据第I+1盏灯的状态,推出第I盏灯在下一秒的状态,因此不能一开始
就改变数组元素的值,必须等一轮分析结束后再一起改变,于是我增加了一个数组用来存储,
各盏灯变化后的状态,等一轮分析结束后再把这个数组的值复制给原数组。依此类推,直到结束。*/
/* 2005-12-24 梁见斌 */
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#define MAX_N 500
#define MAX_M 200000
#define MIN_N 2
#define MIN_M 0
void Change(int Source[], int len);
int main(void)
{
int N;
long M;
int i;
int Source[MAX_N]={0}; //用来存储输入的数据,数据可重复
int CopySource[MAX_N]={0}; // 用来存储输出的数据
do
{
scanf("%d%ld", &N, &M);
fflush(stdin);
} while((N<MIN_N)||(N>MAX_N)||(M<MIN_M)||(M>MAX_M));
for(i=0; i<N; i++)
{
do
{
scanf("%d", &Source[i]);
fflush(stdin);
} while((Source[i]!=0)&&(Source[i]!=1));
}
Change(Source, N);
for(i=0; i<N; i++)
printf("%d\n", Source[i]);
getchar();
return 0;
}
void Change(int Source[], int len)
{
int i;
int CopySource[MAX_N]={0}; // 用来存储输出的数据
for(i=len-1; i>0; i--)
{
if(Source[i]==1) //在每一秒钟,如果第I+1盏灯是亮的,那么第I盏灯在下一秒会变化它的状态
{
if(Source[i-1]==0)
CopySource[i-1] = 1;
else
CopySource[i-1] = 0;
}
else //否则灯不改变状态
CopySource[i-1] = Source[i-1];
}
if(Source[0]==1)//特别的,如果第1盏灯是亮的,那么第N盏灯在下一秒会变化它的状态。
{
if(Source[len-1]==0)
CopySource[len-1] = 1;
else
CopySource[len-1] = 0;
}
else //否则灯不改变状态
CopySource[len-1] = Source[len-1];
for(i=0; i<len; i++) //把新数组的值复制给原数组
{
Source[i] = CopySource[i];
}
}
30 楼
goal00001111 [专家分:4030] 发布于 2005-12-25 09:51:00
4.
/*算法思路:
先读入数据,把M个关系存入结构数组。
给数组长度赋初值len = M;根据输入的原始数据推出新的队员之间的关系 ,即若两个数据显示
的队员关系相同(都为高或低;不考虑“不知道”的情况,因为这不是给出的原始数据中包含
的关系),则推出第三组关系为”高“---可查找整个数组,看这个关系是否已经存在,若不存在,
创建新的数据元素。分析完原始输入数据后,按照同样的方法分析新产生的数据(注意:只分析
新产生的数据,可逆序分析);每一轮都会产生新的数据,依此循环分析,直到没有新的数据产生。
输入要求的关系,可在数组中查询,输出对应的关系(高或低);若所要求的关系不包含在数组中,
则输出 “不知道”。*/
/* 2005-12-24 梁见斌 */
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MIN 1
#define MAX_N 2000
#define MAX_M 50000
#define MAX_K 50000
typedef struct node
{
char g; //存储关系
int A; //存储队员A的号码
int B; //存储队员的B号码
} Relation;
long SolveOld(Relation a[], long len, long add);//根据输入的原始数据推出新的队员之间的关系
long SolveNew(Relation a[], long *len, long add);//分析新产生的数据
void Print(const Relation a[], long len, long K); //输入要求的关系,并输出结果
//各种判断函数
int SearchAA(Relation a[], long len, long num1, long num2);
int SearchAB(Relation a[], long len, long num1, long num2);
int SearchBA(Relation a[], long len, long num1, long num2);
int SearchBB(Relation a[], long len, long num1, long num2);
int main(void)
{
Relation a[MAX_M]; //存储所有的关系结构体
char blank;//为了满足输入的格式,用来吸收一个空格
int N; //存储队员个数
long M, K; //存储M个关系以及K次询问
long len; //存储结构体数组的现有长度
long i;
long add = 0; //累积新得到的关系
do
{
scanf("%d%ld%ld", &N, &M, &K);
fflush(stdin);
} while((N<MIN)||(N>MAX_N)||(M<MIN)||(M>MAX_M)||(K<MIN)||(K>MAX_K));
len = M;
for(i=0; i<len; i++)
{
scanf("%d%d%c%c", &a[i].A, &a[i].B, &blank, &a[i].g);
fflush(stdin);
}
add = SolveOld(a, len, add);//根据输入的原始数据推出新的队员之间的关系
while(add != 0)//如果新得到的数据为0,表示分析完毕,否则重复下列操作
{
add = SolveNew(a, &len, add); //分析新产生的数据
}
Print(a, len, K); //输入要求的关系,并输出结果
getchar();
return 0;
}
void Print(const Relation a[], long len, long K) //输入要求的关系,并输出结果
{
long i, j;
int X, Y; //存储新得到的关系中队员的号码
int flag;
char answer[MAX_M];
for(i=0; i<K; i++) //输入要求的关系
{
scanf("%ld%ld", &X, &Y);
fflush(stdin);
for(flag=0, j=0; j<len; j++)
{
if((X==a[j].A)&&(Y==a[j].B)||(Y==a[j].A)&&(X==a[j].B))
{
answer[i] = a[j].g;
flag = 1;
break;
}
}
if(!flag)
answer[i] = 'N';
}
for(i=0; i<K; i++) //输出结果
{
switch(answer[i])
{
case 'E': puts("低");
break;
case 'F': puts("高");
break;
case 'N': puts("不知道");
break;
}
}
}
我来回复