您的位置:首页 > 编程语言 > Go语言

Google Code Jam 2009 资格赛题目B 程序

2009-11-11 18:27 471 查看
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

#define FALSE 0
#define TRUE !FALSE

struct _Data { /* 定义元素属性:数据,方向,标志,标签 */
int D; /* 存放元素数据值 */
int Direction[4]; /* 存放流向方向[0],[1],[2],[3]分别代表上,左,下,右 */
char flag; /* 标志,为1时表示该元素已经被标记过了 */
char map; /* 标签,按照题目要求从a开始 */
};

struct Node { /* 定义每个CASE的结构体 */
int H; /* 具有多少行 */
int W; /* 具有多少列 */
struct _Data Data[10][10]; /* 最大是10x10的 */
};
struct Node Case[100]; /* 最多有100个CASE */

int d[4][2] = { /* 方向坐标 */
{-1, 0}, /* 上 */
{ 0,-1}, /* 左 */
{ 0, 1}, /* 右 */
{ 1, 0}}; /* 下 */

/*
* 递归函数 输入:当前Case值,当前元素x坐标,当前元素y坐标,当前标签字符
* 说明:递归调用,被标记方向的所有元素均被遍历
*/
int recursive(int l,int x,int y, char c)
{
if ( Case[l].Data[x][y].flag == 1 ) { /* 如果该元素被标记过了,则跳过 */
return TRUE;
}
int i = 0;
Case[l].Data[x][y].flag = 1; /* 标识该元素已经被标记 */
Case[l].Data[x][y].map = c; /* 贴上标签 */
for ( i = 0 ; i < 4 ; i++ ) { /* 四个方向上 */
if ( Case[l].Data[x][y].Direction[i] == 1 ) { /* 如果哪个方向上由方向流动 */
recursive(l,(x+d[i][0]),(y+d[i][1]),c); /* 则流动到那个元素并继续检查流动方向 */
}
}
return TRUE;
}

int main(int argc, char *argv[])
{
FILE *fin=NULL,*fout=NULL; /* 输入输出文件指针 */
char *filein = NULL; /* 输入文件名 */
char *fileout = "B.out"; /* 输出文件名 */

int CaseNum = 0; /* Case有多少个的总共计数 */
int i=0,j=0,k=0,l=0,m=0; /* 变量 */
int iMaxLine = 25; /* 每一行的最大值 */
int min=0; /* 存放最小元素变量 */
int tx=0,ty=0; /* 辅助坐标,四个方向搜索时用到 */
int ttx=0,tty=0; /* 辅助坐标,确定有方向流动时用到 */
int Row=0; /* 辅助变量,统计Case数据行数 */
int dir = 0; /* 方向变量,初始值为-1,当有方向流动时从[0,3]中赋值 */

char Storage[1100][25]; /* 临时存储数据数组 */
char cLine[25] = {0}; /* 临时存储每一行字符数组 */
char *delim = " "; /* 分割字符 */
char *p = NULL; /* 指针变量,分割字符串时用到 */

if (argc != 2) {
fprintf(stderr,"Usage: %s filein./n",argv[0]);
return FALSE;
}
filein = argv[1];
fin = fopen(filein,"r");
fout = fopen(fileout,"w");
if (fin == NULL) {
fprintf(stderr,"open filein err./n");
return FALSE;
} else if (fout == NULL) {
fprintf(stderr,"open fileout err./n");
return FALSE;
}
/* 输入文件和输出文件的相关操作及出错处理 */

while (fgets(cLine,iMaxLine,fin) != NULL) { /* 把数据都读出来 */
if (i == 0) {
sscanf(cLine,"%d",&CaseNum); /* 读出总共的Case数 */
} else {
strncpy(Storage[i-1],cLine,strlen(cLine)); /* 先把数据暂时存放在Storage里面 */
}
i++;
Row++;
}
fclose(fin); /* 关闭输入文件 */
Row--; /* 记录Storage总共有多少行 */
for ( i = 0 ,j = 0 ; i < Row ; j++ ) { /* 把数据读入Case结构体中 */
sscanf(Storage[i],"%d %d",&Case[j].H,&Case[j].W); /* Case的第一行是 行 列 */
i++;
for ( k = 0 ; k < Case[j].H ; k++ ) { /* 继续读H行 */
m = 0;
p = strtok(Storage[i+k],delim); /* 以空格作为分界符,分割字符串 */
Case[j].Data[k][m++].D = atoi(p);
while((p = strtok(NULL,delim))) {
Case[j].Data[k][m++].D = atoi(p);
}
}
i += k; /* 跳过H行 */
}
#if 1
for ( l = 0 ; l < CaseNum ; l ++ ) { /* 循环Case的个数 */
fprintf(fout,"Case #%d:/n",l+1);
#if 1
for ( i = 0 ; i < Case[l].H ; i ++ ) { /* 遍历一个Case */
for ( j = 0 ; j < Case[l].W ; j++ ) {
min = Case[l].Data[i][j].D;
dir = -1;
for ( k = 0 ; k < 4 ; k++ ) { /* 搜索这个Case的每一个元素的四个方向上的值 */
tx = i+d[k][0];
ty = j+d[k][1];
if ( tx<0 || ty<0 || tx>=Case[l].H || ty >= Case[l].W) { /* 边界检查 */
continue;
}
if (Case[l].Data[tx][ty].D < min ){ /* 比较四个方向上的值的大小,取最小的 */
min = Case[l].Data[tx][ty].D;
dir = k;
ttx = tx;
tty = ty;
}
}
if ( dir >= 0 ) { /* 当当前元素四周有更小的元素存在时,标记流动方向 */
Case[l].Data[i][j].Direction[dir] = Case[l].Data[ttx][tty].Direction[3-dir] = 1;
} /* 标记该元素的方向和四周的最小元素的方向,这个方向是互相的 */
}
}
#endif
k = 0; /* 重复利用一个变量 */
#if 1
for ( i = 0 ; i < Case[l].H ; i++ ) { /* 递归,给Case中的每一个元素上标签 */
for ( j = 0 ; j < Case[l].W ; j++ ) {
if ( Case[l].Data[i][j].flag != 1) { /* 如果这个元素没有被标记过 */
recursive(l,i,j,'a'+k);
k++; /* 按照规定标签为:a~z */
}
}
}
#endif
#if 1
for ( i = 0 ; i < Case[l].H ; i++ ) { /* 输出结果 */
for ( j = 0 ; j < Case[l].W ; j++ ) {
fprintf(fout,"%c",Case[l].Data[i][j].map);
if ( j < Case[l].W-1 ) {
fprintf(fout," ");
}
}
fprintf(fout,"/n");
}
#endif
}
fclose(fout);
#endif
return TRUE;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: