湖南省第六届大学生程序设计大赛原题 F Biggest Number (UVA1182)
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)的更多相关文章
- 湖南省第八届大学生程序设计大赛原题 D - 平方根大搜索 UVA 12505 - Searching in sqrt(n)
http://acm.hust.edu.cn/vjudge/contest/view.action?cid=30746#problem/D D - 平方根大搜索 UVA12505 - Searchin ...
- 湖南生第八届大学生程序设计大赛原题 C-Updating a Dictionary(UVA12504 - Updating a Dictionary)
UVA12504 - Updating a Dictionary 给出两个字符串,以相同的格式表示原字典和更新后的字典.要求找出新字典和旧字典的不同,以规定的格式输出. 算法操作: (1)处理旧字典, ...
- NYOJ-712 探寻宝藏(第六届河南省程序设计大赛)
探 寻 宝 藏 时间限制:1000 ms | 内存限制:65535 KB 难度:5 描述 传说HMH大沙漠中有一个M*N迷宫,里面藏有许多宝物.某天,Dr.Kong找到了迷宫的地图,他发现迷宫 ...
- 河南省第六届ACM程序设计大赛
C: 最舒适的路线 (并查集) #include<cstdio> #include<cstring> #include<iostream> #include< ...
- River Crossing---河南省第六届大学生程序设计竞赛
题目描述 Afandi is herding N sheep across the expanses of grassland when he finds himself blocked by a ...
- Contest - 中南大学第六届大学生程序设计竞赛(Semilive)
题1:1160十进制-十六进制 注意他给的数据范围 2^31,int是 2^31-1 #include<iostream> using namespace std; int main() ...
- 校第十六届大学生程序设计竞赛暨2016省赛集训队选拔赛(Problem E)
Problem E Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total ...
- ZOJ 4100 浙江省第16届大学生程序设计竞赛 A题 Vertices in the Pocket 线段树+并查集
正赛的时候完全没看这个题,事后winterzz告诉我他想出来的解法. 首先题意是给出n个点,m次操作. 操作有一种是连接两个点,另一种是求此时再为这个图连k条边,最少和最多能有几个联通块. 最少的求法 ...
- ZOJ 4103 浙江省第16届大学生程序设计竞赛 D题 Traveler 构造
这个题,正赛的时候也没有过,不过其实已经有了正确的解法,可惜时间不多了,就没有去尝试. 题意是有n个点,i点能通向i-1,然后i和i*2.i*2+1互通. 请你构造一种路径从1能走完所有点,并且不重复 ...
随机推荐
- linux修改主机名-IP
1.查看当前主机名 hostname 2. ifconfig 显示所有网络接口的信息 ifconfig eth0 显示网卡eth0的信息 3.临时修改主机名 hostname rusky. ...
- 知问前端--Ajax
本节课主要是创建一个问题表,将提问数据通过 ajax 方式提交出去.然后对内容显示进行布局,实现内容部分隐藏和完整显示的功能. 一.Ajax 提问创建一个数据表:question,分别建立:id.ti ...
- .net I/O操作 导图
稍微总结下,System.IO提供了四种类型来实现,对单个文件和计算机目录结构的操作.Directory和File通过静态成员实现建立.删除.复制和移动操作(上图没有提及).而FileInfo和Dir ...
- OpenSuse下编译MonoDevelop
当访问Monodevelop.com官网下载的安装包,安装后,发现并不是最新版.在OpenSuse下载的是3.0版本.根据官网的指示,可以自己下载源码进行编译.按官网的指引: 1. $ git clo ...
- 为什么class中属性以空格分隔?
1 div.contain .blue{color:blue;}/*后代选择器*/2 div.contain.blue{color:blue;} /*多类选择器*/ 以上两种规则分别应用的元素如下: ...
- DNN Module - Responsive Html Tabs 3 介绍
Responsive Html Tabs 模块可以运行于DNN7及以上版本,支持响应式.用户界面较为友好,可以插入自定义的HTML. Demo This is a user-friendly, ful ...
- oracle commit之后的数据回滚
当你晕晕乎乎的执行了commit之后,突然间意思到自己点错了,那说明你和我碰到了一样的问题. 瞬间感觉大冷天头顶冒汗,那就说明你的感觉对了.废话少说,下面是我的办法: 下面的例子都是以Test表为例. ...
- POJ2739 Sum of Consecutive Prime Numbers(尺取法)
POJ2739 Sum of Consecutive Prime Numbers 题目大意:给出一个整数,如果有一段连续的素数之和等于该数,即满足要求,求出这种连续的素数的个数 水题:艾氏筛法打表+尺 ...
- Winform控件缩写
控件名称 缩写 Buttom按钮 Btn CheckBox复选框 Chk ColumnHeader视图列表头 Col ComboBox组合框 Cbo ContextMenu快捷菜单 Ctm DataG ...
- NodeJs简单七行爬虫--爬取自己Qzone的说说并存入数据库
没有那么难的,嘿嘿,说起来呢其实挺简单的,或者不能叫爬虫,只需要将自己的数据加载到程序里再进行解析就可以了,如果说你的Qzone是向所有人开放的,那么就有一个JSONP的接口,这么说来就简单了,也就不 ...