Biggest Number

http://acm.hust.edu.cn/vjudge/contest/view.action?cid=30851#problem/F

解题思路:DFS(检索)+BFS(探路)=强剪枝

一看就知道是搜索题,只是,要是DFS裸搜,真的会超时。时间,非常紧!

做该题的时候,要无时无刻不忘剪枝,抓住一切剪枝的机会,剪吧!

(1)用flag记录当前检索的值与当前已经检索到的最大值的关系,一但有机会,就要剪掉那些检索到的值会比当前最大值要小的“残枝败叶”。

(2)每次DFS检索之前,一定要用BFS“探路”,要是该次检索的值的最大长度小于当前最大值的最大长度,赶紧剪掉。这次搜索到的值不可能比当前最大值大,搜了也白搜,赶紧结束,节约时间。

这里我给出两个代码,一个是参考别人的代码注释来得,一种是用自己的想法从写得到的。

首先,我承认自己做不出来,一直超时。但我是个锲而不舍的孩子,在网上查了资料,弄懂了。代码主人,只在博客中给出代码,没有思路描绘,也没有注释。我做了注释后的成果如下:

1532762 20114045007 F Accepted 0 KB 329 ms C++ 4.5.3 4881 B 2013-09-03 20:55:11
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
struct node
{
int x,y;
} queue[1000];
int n,m;
int Max,flag,tatal; //当前检索到的最大值的长度、当前检索值首数字与当前检索到的最大值的首数字的关系、数字总数
char map[20][20]; //输入地图存储
char ans[35],stack[35]; //当前检索到的最大值、当前检索值的情况
int dir[4][2]= {-1,0,0,-1,0,1,1,0}; //四个方向
bool yes(int x,int y)
{
return x>=0&&x<n&&y>=0&&y<m; //该点是否在地图中,是就返回true
}
int bfs(int x,int y) //(x,y)处往后还能搜索到多少位有效数字
{
node t;
char g[20][20];
for(int i=0; i<n; i++)strcpy(g[i],map[i]); //将g中的值赋为map
int head,tail; //队列前后”指针“
head=tail=0; //队列为空
t.x=x,t.y=y; //其实节点,用于入队
queue[tail++]=t; //数组模拟队列
while(head<tail) //队列不为空
{
x=queue[head].x;
y=queue[head++].y; //取出队头元素,队头后移一位
for(int i=0; i<4; i++) //四面查找
{
int xx=x+dir[i][0];
int yy=y+dir[i][1];
if(!yes(xx,yy)||g[xx][yy]=='#')continue; //该点不在地图中,该点不可处理【不处理该点】
g[xx][yy]='#'; //要处理该点,标记,预防重处理
t.x=xx,t.y=yy; //记录情况
queue[tail++]=t; //新节点入“队”
}
}
return head; //该次处理的点数
}
void dfs(int x,int y,int cnt) //当前检索点的坐标情况,当前检索到的数的长度
{
if(Max<cnt||(Max==cnt&&flag==1)) //当前检索到的数的长度大于当前检索到的最大的数的总长度“或”长度相等但是当前值首数字比较大
//当前检索到的值必定大于当前检索到的“最大值”【强剪枝2】
{
stack[cnt]=0; //字符串结束标志【别忘了,字符数组没有结束标志会输出错误的】
strcpy(ans,stack); //将当前值赋给”最大值“
Max=cnt; //改变最大值的长度
flag=0; //大小不确定
}
int res=bfs(x,y); //该点后面还能搜索到res个有效数字
if(res+cnt-1<Max||(res+cnt-1==Max&&flag==-1))return; //若该点参与的检索中的有效数字的最大长度小于当前检索到的数字中的最大值的长度
//长度相等,但是该次检索的数字要小【这个数肯定小于当前检索到的最大值】直接结束搜索【强剪枝3】
for(int i=0; i<4; i++) //当前的搜索得到的数肯定会大于当前检索到的最大值,【搜索继续】
{
int xx=x+dir[i][0];
int yy=y+dir[i][1];
if(!yes(xx,yy)||map[xx][yy]=='#')continue; //该点不在地图中,或该点不可处理【不作处理】【常规剪枝】
if(flag!=1&&ans[cnt]>map[xx][yy]&&tatal==Max)continue; //当前检索的值不可能大于当前检索到的最大值【强剪枝4】
stack[cnt]=map[xx][yy]; //检索到的数字可用,加入到临时【当前检索值的情况】中
map[xx][yy]='#'; //记得标记哦,检索过的就不要再检索了
if(flag==0) //【】【】大小不确定
{
if(cnt>=Max)flag=1; //长度,当前检索到的比较大
else if(ans[cnt]==stack[cnt])flag=0; //长度想相同就比首字母 【大小不确定】
else if(ans[cnt]<stack[cnt])flag=1; //当前检索到的i较大
else flag=-1; //当前检索到的比较小
dfs(xx,yy,cnt+1); //长度加1
flag=0;//【大小不确定】
}
else dfs(xx,yy,cnt+1); //若大小确定,继续检索
map[xx][yy]=stack[cnt]; //搜索归来,抹去标记
}
}
int main()
{
while(scanf("%d%d",&n,&m)&&n+m)
{
tatal=0;
for(int i=0; i<n; i++)
{
scanf("%s",map+i);
for(int j=0; j<m; j++)
{
if(map[i][j]!='#')tatal++;
}
}
Max=1;
memset(ans,0,sizeof(ans));
for(int i=0; i<n; i++)
{
for(int j=0; j<m; j++)
{
if(map[i][j]=='#')continue;
if(Max==tatal&&ans[0]>map[i][j])continue; //当前检索到的最大值,长度已达到最长&&开头数字比当前检索数字大
//以当前数字开头检索到的最大值肯定小于当前检索到的最大值【强剪枝1】
stack[0]=map[i][j];
map[i][j]='#'; //访问标记
if(ans[0]==stack[0])flag=0;//大小不确定
else if(ans[0]<stack[0])flag=1; //大于
else flag=-1; //小于
dfs(i,j,1);
map[i][j]=stack[0]; //搜索归来,抹掉标记
}
}
printf("%s\n",ans); //输出最终答案
}
return 0;
}

原码转自:http://blog.csdn.net/andring/article/details/7376129

本人代码:更新中。。。

湖南省第六届大学生程序设计大赛原题 F Biggest Number (UVA1182)的更多相关文章

  1. 湖南省第八届大学生程序设计大赛原题 D - 平方根大搜索 UVA 12505 - Searching in sqrt(n)

    http://acm.hust.edu.cn/vjudge/contest/view.action?cid=30746#problem/D D - 平方根大搜索 UVA12505 - Searchin ...

  2. 湖南生第八届大学生程序设计大赛原题 C-Updating a Dictionary(UVA12504 - Updating a Dictionary)

    UVA12504 - Updating a Dictionary 给出两个字符串,以相同的格式表示原字典和更新后的字典.要求找出新字典和旧字典的不同,以规定的格式输出. 算法操作: (1)处理旧字典, ...

  3. NYOJ-712 探寻宝藏(第六届河南省程序设计大赛)

    探 寻 宝 藏 时间限制:1000 ms  |  内存限制:65535 KB 难度:5   描述 传说HMH大沙漠中有一个M*N迷宫,里面藏有许多宝物.某天,Dr.Kong找到了迷宫的地图,他发现迷宫 ...

  4. 河南省第六届ACM程序设计大赛

    C:  最舒适的路线 (并查集) #include<cstdio> #include<cstring> #include<iostream> #include< ...

  5. River Crossing---河南省第六届大学生程序设计竞赛

    题目描述 Afandi is herding N sheep across the expanses of grassland  when he finds himself blocked by a ...

  6. Contest - 中南大学第六届大学生程序设计竞赛(Semilive)

    题1:1160十进制-十六进制 注意他给的数据范围 2^31,int是 2^31-1 #include<iostream> using namespace std; int main() ...

  7. 校第十六届大学生程序设计竞赛暨2016省赛集训队选拔赛(Problem E)

    Problem E Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total ...

  8. ZOJ 4100 浙江省第16届大学生程序设计竞赛 A题 Vertices in the Pocket 线段树+并查集

    正赛的时候完全没看这个题,事后winterzz告诉我他想出来的解法. 首先题意是给出n个点,m次操作. 操作有一种是连接两个点,另一种是求此时再为这个图连k条边,最少和最多能有几个联通块. 最少的求法 ...

  9. ZOJ 4103 浙江省第16届大学生程序设计竞赛 D题 Traveler 构造

    这个题,正赛的时候也没有过,不过其实已经有了正确的解法,可惜时间不多了,就没有去尝试. 题意是有n个点,i点能通向i-1,然后i和i*2.i*2+1互通. 请你构造一种路径从1能走完所有点,并且不重复 ...

随机推荐

  1. POJ 2455Secret Milking Machine(二分+网络流之最大流)

    题目地址:POJ2455 手残真浪费时间啊..又拖到了今天才找出了错误..每晚两道题不知不觉又变回了每晚一道题...sad.. 第一次在isap中忘记调用bfs,第二次则是遍历的时候竟然是从1開始遍历 ...

  2. 如何用Github的gh-pages分支展示自己的项目

    很多新同学觉得github不就是一个代码托管所吗,如何能展示项目呢?其实完全可以借助Github的gh-pages打造出自己的一个作品集,无论是对自己的提升整合还是日后的面试都大有裨益. 前置准备 G ...

  3. ExifInterface 多媒体文件附加信息

    简介         ExifInterface类主要描述多媒体文件比如JPG格式图片的一些附加信息,包括拍摄时的光圈.快门.白平衡.ISO.焦距.日期时间等各种和拍摄条件以及相机品牌.型号.色彩编码 ...

  4. Android -------- 网络访问数据

  5. Android-操作栏之选项菜单

    回答第一个问题:什么是选项菜单?答:选项菜单就是可以显示在操作栏上的菜单. 菜单的视图需要建立在res/menu下. 其中,showAsAction属性用于指定菜单选项是显示在操作栏还是隐藏到溢出菜单 ...

  6. [c#]asp.net开发微信公众平台(7)前6篇的整体框架demo源码

    这里给出的demo是具备整体框架的微信公众平台源码, 所谓demo就是拿过去就可以直接演示使用的东西,  当然不会具备非常详细的具体到业务层面.数据层面的东西, 每个人都可以在此基础上自由发挥,  只 ...

  7. initWithFrame和initWithCoder区别

    当我们所写的程序里没用用Nib文件(XIB)时,用代码控制视图内容,需要调用initWithFrame去初始化 - (id)initWithFrame:(CGRect)frame{ if (self  ...

  8. 武汉科技大学ACM :1005: 零起点学算法101——手机短号

    Problem Description 大家都知道,手机号是一个11位长的数字串,同时,作为学生,还可以申请加入校园网,如果加入成功,你将另外拥有一个短号.假设所有的短号都是是 6+手机号的后5位,比 ...

  9. C++中的dynamic_cast和static_cast

    代码: #include <cstdio> #include <iostream> using namespace std; class A{ public: virtual ...

  10. shell的string operator

    ${varname:-word} 如果varname存在并且不为nil,那么返回varname的值,否则返回word.这个常用来在varname未定义时返回默认值 ${varname:=word} 如 ...