湖南省第6届程序大赛第6题

Problem F

Biggest Number

You have a maze with obstacles and non-zero digits in it:

You can start from any square, walk in the maze, and finally stop at some square. Each step, you may only walk into one of the four neighbouring squares (up, down, left, right) and you cannot walk into obstacles or walk into a square more than once. When you finish, you can get a number by writing down the digits you encounter in the same order as you meet them. For example, you can get numbers 9784, 4832145 etc. The biggest number you can get is 791452384, shown in the picture above.

Your task is to find the biggest number you can get.

Input

There will be at most 25 test cases. Each test begins with two integers R and C (2<=R,C<=15, R*C<=30), the number of rows and columns of the maze. The next R rows represent the maze. Each line contains exactly C characters (without leading or trailing spaces), each of them will be either ‘#‘ or one of the nine non-zero digits. There will be at least one non-obstacle squares (i.e. squares with a non-zero digit in it) in the maze. The input is terminated by a test case with R=C=0, you should not process it.

Output

For each test case, print the biggest number you can find, on a single line.


Sample Input


Output for the Sample Input


3 7

##9784#

##123##

##45###

0 0


791452384

这道题目的话,就是让你输入的是n行m列。只有数字是可以走的,你可以从任何一个位置开始,你路过的地方的数字序列为aa[],要求输出序列比较最大的。

题意是很明确的搜索,但是问题是时间。如果我每一个地方都进行一次dfs或者bfs的话,毫无疑问,肯定会超时。所以我们的思路应该放在如何去剪枝,如何去

优化搜索的时间。最后的做法就是从每一个可以出发的地方都遍历一次,在中间加上剪枝就可以过了。

  1 #include <cstdio>
  2 #include <cstring>
  3 using namespace std;
  4 int r,c,i,j;//行 列
  5 char a[20][20]; //字符串的保存
  6 int used[20][20];//路径开头的标记
  7 int ans[100];//保存最大的路径
  8 int ansl;//保存最大路径的长度
  9 int aa[100];//记录当前查找时候的路径
 10 int zhan[100][2];// 就是一个栈  用来求这一个点可以往后面走多远
 11 int used1[20][20];// 还是路径的记录
 12 int neigh[4][2]={{0,1},{1,0},{0,-1},{-1,0}};//可以走的4个方向
 13 int z;//表示当前查找的路径是否比已经记录的最大路径前缀大
 14 void search(int x,int y,int l)//搜索  x,y代表当前所在的位置   l代表当前路劲的长度
 15 {
 16     int i,j,top,bottom,xx,yy;
 17     if ((l>ansl)||((l==ansl)&&(z==1)))//位数比以前的大或者 位数一样 但是数值大的时候  更新ans数组  和ansl的值
 18     {
 19         memcpy(ans,aa,sizeof(ans));
 20         ansl=l;
 21         z=0;
 22     }
 23     memset(used1,0,sizeof(used1));
 24     used1[x][y]=1;
 25     top=0;bottom=1;
 26     zhan[0][0]=x;
 27     zhan[0][1]=y;
 28     while (top<bottom)//从当前的位置  后面还能走多少步
 29     {
 30         for (i=0;i<4;i++)
 31         {
 32             xx=zhan[top][0]+neigh[i][0];
 33             yy=zhan[top][1]+neigh[i][1];
 34             if ((xx>=0)&&(xx<r)&&(yy>=0)&&(yy<c)&&(a[xx][yy]!=‘#‘)&&(used[xx][yy]==0)&&(used1[xx][yy]==0))
 35             {
 36                 zhan[bottom][0]=xx;
 37                 zhan[bottom][1]=yy;
 38                 used1[xx][yy]=1;
 39                 bottom++;
 40             }
 41         }
 42         top++;
 43     }
 44     if (l+top-1<ansl) return;//如果当前长度+后继结点构成最长数长度<最大数长度 结束搜索
 45     if ((l+top-1==ansl)&&(z==-1)) return;//如果当前长度+后继结点构成最长数长度=最大数长度 但是比最长数小  同样结束搜索
 46     for (i=0;i<4;i++)
 47     {
 48         xx=x+neigh[i][0];
 49         yy=y+neigh[i][1];
 50         if ((xx>=0)&&(xx<r)&&(yy>=0)&&(yy<c)&&(a[xx][yy]!=‘#‘)&&(used[xx][yy]==0))
 51         {
 52             aa[l]=a[xx][yy]-‘0‘;
 53             used[xx][yy]=1;
 54             if (z!=0)
 55                 search(xx,yy,l+1);//前面的数值已经比较出大小的  后面的数值不会对大小的比较产生影响
 56             else
 57                 if (l>=ansl)
 58                 {
 59                     z=1;
 60                     search(xx,yy,l+1);
 61                     z=0;
 62                 }
 63                 else
 64                 {
 65                     if (aa[l]>ans[l])
 66                     {
 67                         z=1;
 68                         search(xx,yy,l+1);
 69                         z=0;
 70                     }
 71                     else if (aa[l]==ans[l])
 72                     {
 73                         z=0;
 74                         search(xx,yy,l+1);
 75                         z=0;
 76                     }
 77                     else
 78                     {
 79                         z=-1;
 80                         search(xx,yy,l+1);
 81                         z=0;
 82                     }
 83                 }
 84             used[xx][yy]=0;
 85         }
 86     }
 87 }
 88
 89 int main()
 90 {
 91  92     while (~scanf("%d%d",&r,&c)&&c&&r)
 93     {
 94         for (i=0;i<r;i++)
 95             scanf("%s",a[i]);
 96         memset(ans,0,sizeof(ans));
 97         ans[0]=-1;
 98         ansl=1;
 99         memset(aa,0,sizeof(aa));
100         for (i=0;i<r;i++)
101             for (j=0;j<c;j++)//遍历每一个不是#号的地方   因为这一些地方都可以作为出发点
102                 if (a[i][j]!=‘#‘)
103                 {
104                     used[i][j]=1;  // 记录  路径的开始
105                     aa[0]=a[i][j]-‘0‘; //aa是用来保存当前搜索的路径
106                     if (a[i][j]-‘0‘>ans[0])//比较大小  z=1代表大  0代表一样  -1代表小
107                     {
108                         z=1;
109                         search(i,j,1);//搜索
110                     }
111                     else if (a[i][j]-‘0‘==ans[0])
112                     {
113                         z=0;
114                         search(i,j,1);
115                     }
116                     else
117                     {
118                         z=-1;
119                         search(i,j,1);
120                     }
121                     used[i][j]=0;
122                 }
123         for (i=0;i<ansl;i++)
124             printf("%d",ans[i]);
125         printf("\n");
126     }
127     return 0;
128 }
时间: 2024-10-13 04:27:46

湖南省第6届程序大赛第6题的相关文章

湖南省第6届程序大赛第3题 数字整除

题目C 数字整除 定理:把一个至少两位的正整数的个位数字去掉,再从余下的数中减去个位数的5倍.当且仅当差是17的倍数时,原数也是17的倍数 . 例如,34是17的倍数,因为3-20=-17是17的倍数:201不是17的倍数,因为20-5=15不是17的倍数.输入一个正整数n,你的任务是判断它是否是17的倍数. 输入 输入文件最多包含10组测试数据,每个数据占一行,仅包含一个正整数n(1<=n<=10100),表示待判断的正整数.n=0表示输入结束,你的程序不应当处理这一行. 输出 对于每组测试

湖南省第6届程序大赛第4题

题目D 台球碰撞 在平面直角坐标系下,台球桌是一个左下角在(0,0),右上角在(L,W)的矩形.有一个球心在(x,y),半径为R的圆形母球放在台球桌上(整个球都在台球桌内).受撞击后,球沿极角为a的射线(即:x正半轴逆时针旋转到此射线的角度为a)飞出,每次碰到球桌时均发生完全弹性碰撞(球的速率不变,反射角等于入射角). 如果球的速率为v,s个时间单位之后球心在什么地方? 输入 输入文件最多包含25组测试数据,每个数据仅一行,包含8个正整数L,W,x,y,R,a,v,s(100<=L,W<=10

湖南省第6届程序大赛第5题

题目E 内部收益率 在金融中,我们有时会用内部收益率IRR来评价项目的投资财务效益,它等于使得投资净现值NPV等于0的贴现率.换句话说,给定项目的期数T.初始现金流CF0和项目各期的现金流CF1, CF2, ...,CFT,IRR是下面方程的解: 为了简单起见,本题假定:除了项目启动时有一笔投入(即初始现金流CF0 < 0)之外,其余各期均能赚钱(即对于所有i=1,2,...,T,CFi> 0).根据定义,IRR可以是负数,但不能大于-1. 输入 输入文件最多包含25组测试数据,每个数据占两行

湖南省第6届程序大赛第二题 弟弟的作业

题目B 弟弟的作业 你的弟弟刚做完了“100以内数的加减法”这部分的作业,请你帮他检查一下.每道题目(包括弟弟的答案)的格式为a+b=c或者a-b=c,其中a和b是作业中给出的,均为不超过100的非负整数:c是弟弟算出的答案,可能是不超过200的非负整数,也可能是单个字符"?",表示他不会算. 输入 输入文件包含不超过100行,以文件结束符结尾.每行包含一道题目,格式保证符合上述规定,且不包含任何空白字符.输入的所有整数均不含前导0. 输出 输出仅一行,包含一个非负整数,即弟弟答对的题

湖南省第6届程序大赛 Repairing a Road

Problem G Repairing a Road You live in a small town with R bidirectional roads connecting C crossings and you want to go from crossing 1 to crossing C as soon as possible. You can visit other crossings before arriving at crossing C, but it’s not mand

湖南省第6届程序设计大赛第一题 汽水瓶

题目A 汽水瓶 有这样一道智力题:“某商店规定:三个空汽水瓶可以换一瓶汽水.小张手上有十个空汽水瓶,她最多可以换多少瓶汽水喝?”答案是5瓶,方法如下:先用9个空瓶子换3瓶汽水,喝掉3瓶满的,喝完以后4个空瓶子,用3个再换一瓶,喝掉这瓶满的,这时候剩2个空瓶子.然后你让老板先借给你一瓶汽水,喝掉这瓶满的,喝完以后用3个空瓶子换一瓶满的还给老板.如果小张手上有n个空汽水瓶,最多可以换多少瓶汽水喝? 输入 输入文件最多包含10组测试数据,每个数据占一行,仅包含一个正整数n(1<=n<=100),表示

湖南省第六届大学生计算机程序设计竞赛---汽水瓶

1006: 汽水瓶 时间限制: 1 Sec  内存限制: 128 MB 提交: 3  解决: 3 [提交][状态][讨论版] 题目描写叙述 有这样一道智力题:"某商店规定:三个空汽水瓶能够换一瓶汽水.小张手上有十个空汽水瓶.她最多能够换多少瓶汽水喝?"答案是5瓶,方法例如以下:先用9个空瓶子换3瓶汽水,喝掉3瓶满的,喝完以后4个空瓶子,用3个再换一瓶,喝掉这瓶满的,这时候剩2个空瓶子. 然后你让老板先借给你一瓶汽水,喝掉这瓶满的,喝完以后用3个空瓶子换一瓶满的还给老板.假设小张手上有n

湖南省第六届大学生计算机程序设计竞赛---数字整除

1008: 数字整除 时间限制: 1 Sec  内存限制: 128 MB 提交: 6  解决: 4 [提交][状态][讨论版] 题目描述 定理:把一个至少两位的正整数的个位数字去掉,再从余下的数中减去个位数的5倍.当且仅当差是17的倍数时,原数也是17的倍数 . 例如,34是17的倍数,因为3-20=-17是17的倍数:201不是17的倍数,因为20-5=15不是17的倍数.输入一个正整数n,你的任务是判断它是否是17的倍数. 输入 输入文件最多包含10组测试数据,每个数据占一行,仅包含一个正整

“青软杯”安徽科技学院第六届程序设计大赛_专业组

Contest - "青软杯"安徽科技学院第六届程序设计大赛_专业组 Start time:  2015-04-18 08:00:00.0  End time:  2015-04-18 12:00:00.0 Current System Time:  2015-04-21 00:07:42.57  Contest Status:   Ended 关于举办"青软杯"安徽科技学院 第六届程序设计大赛通知 ACM 国际大学生程序设计竞赛 (International Co