现在的位置: 首页 > 综合 > 正文

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

2013年01月08日 ⁄ 综合 ⁄ 共 3471字 ⁄ 字号 评论关闭

 #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;
}

抱歉!评论已关闭.