湖南省第六届省赛题 Biggest Number (dfs+bfs,好题)

Biggest Number

时间限制:1000 ms  |  内存限制:65535 KB

难度:4

描述

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.

输入
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.
输出
For each test case, print the biggest number you can find, on a single line.
样例输入
3 7
##9784#
##123##
##45###
0 0
样例输出
791452384
来源
湖南省第六届大学生计算机程序设计竞赛
题解:非常巧妙地剪枝想法,每次DFS一个位置的时候,处理它能够到达的所有的点,我们假设这些点都是沿着它可以到达的,如果当前点的数量+当前的搜索长度<已经得到的最优解的长度,那么这段必定是可以减掉的,因为无论怎么走都达不到最优解的长度了.还有一种就是能够达到点的数量+当前的搜索长度 = 已经得到的最优解的长度,那么我们只要在当前搜索的解后面添一个最大的数字 ‘9‘,如果这样的结果字典序还比已经得到的最优解的字典序小,那么也没有搜索下去的必要了,直接剪枝,这里的BFS按照我的理解就相当于一个估价函数,让结果一直往正确的方向走.很厉害的题目。
还有一个小插曲:就是关于手动队列和STL自带队列,自带队列在某些时候要慎用,比如说这个题,BFS调用的次数比较多,给大家看一下两者的时间。

(手动队列)

(STL自带)

一直超时找不到原因,改成手动队列跑得飞快,还有就是 string 类型也要谨慎使用,这些STL自带功能会消耗时间

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <string>
#include <queue>
using namespace std;
const int N = 35;
int n,m,MAX;
char mp[N][N];
bool flag[N][N];
bool vis[N][N];
int dir[][2] = {{1,0},{-1,0},{0,-1},{0,1}};
struct Node{
    int x,y;
};
char res[N],ans[N],ans1[N];
bool check(int x,int y){
    if(x<1||x>n||y<1||y>m||mp[x][y]==‘#‘) return false;
    return true;
}
Node q[N * N];
int bfs(int x,int y){
    memset(flag,0,sizeof(flag));
    int head = 0, tail = 0,ret = 0;;
    q[tail].x = x;  ///手动队列非常快
    q[tail++].y = y;
    flag[x][y] = true;
    while(head!= tail){
        int nowx = q[head].x;
        int nowy = q[head++].y;
        for(int i=0;i<4;i++){
            int nextx = nowx+dir[i][0];
            int nexty = nowy+dir[i][1];
            if(!check(nextx,nexty)||flag[nextx][nexty]||vis[nextx][nexty]) continue;
            ret++;
            flag[nextx][nexty] = true;
            q[tail].x = nextx;
            q[tail++].y = nexty;
        }
    }
    return ret;
}

void dfs(int x,int y,int step){
    if(step>MAX||step==MAX&&strcmp(ans,res)>0){
        MAX = step;
        strcpy(res,ans);
    }
    int GO = bfs(x,y); ///预处理最好的情况,所有点都可达
    strcpy(ans1,ans);
    ans1[step] = ‘9‘;
    if(GO+step<MAX||GO+step==MAX&&strcmp(ans1,res)<0) return; ///剪枝,(x,y)能够走的距离 < 答案
    for(int i=0;i<4;i++){
         int nextx = x+dir[i][0];
         int nexty = y+dir[i][1];
         if(!check(nextx,nexty)||vis[nextx][nexty]) continue;
         vis[nextx][nexty] = true;
         ans[step] = mp[nextx][nexty];
         dfs(nextx,nexty,step+1);
         ans[step] = 0;
         vis[nextx][nexty] = false;
    }
}
int main()
{
    freopen("f.in","r",stdin);
   freopen("f.txt","w",stdout);
    while(scanf("%d%d",&n,&m)!=EOF,n+m){
        int tot = 0;
        for(int i=1;i<=n;i++){
            scanf("%s",mp[i]+1);
            for(int j=1;j<=m;j++){
                if(mp[i][j]!=‘#‘) tot++;
            }
        }
        memset(res,0,sizeof(res));
        MAX = -1;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                if(mp[i][j]==‘#‘||MAX==tot&&mp[i][j]<res[0]) continue;
                memset(vis,false,sizeof(vis));
                ans[0] = mp[i][j];
                vis[i][j] = true;
                dfs(i,j,1);
            }
        }
        printf("%s\n",res);
    }
    return 0;
}
/**
5 6
245356
342534
534635
423535
324345
*/
时间: 2024-10-20 15:19:15

湖南省第六届省赛题 Biggest Number (dfs+bfs,好题)的相关文章

UVA - 11882 Biggest Number(dfs+bfs+强剪枝)

题目大意:给出一个方格矩阵,矩阵中有数字0~9,任选一个格子为起点,将走过的数字连起来构成一个数,找出最大的那个数,每个格子只能走一次. 题目分析:DFS.剪枝方案:在当前的处境下,找出所有还能到达的点的个数,若当前数字的长度加上个数仍小于目前最优答案的长度,则剪去:若长度相等,则将所有还能到达的数字按从大到小排序后连到当前数字上,如果还比目前最优解小,则减去.找出所有还能到达的点的过程用BFS实现. 1 #pragma comment(linker, "/STACK:1024000000,10

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

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

湖南省第六届大学生计算机程序设计竞赛---弟弟的作业

1007: 弟弟的作业 时间限制: 1 Sec  内存限制: 128 MB 提交: 3  解决: 3 [提交][状态][讨论版] 题目描述 你的弟弟刚做完了"100以内数的加减法"这部分的作业,请你帮他检查一下.每道题目(包括弟弟的答案)的格式为a+b=c或者a-b=c,其中a和b是作业中给出的,均为不超过100的非负整数:c是弟弟算出的答案,可能是不超过200的非负整数,也可能是单个字符"?",表示他不会算. 输入 输入文件包含不超过100行,以文件结束符结尾.每

hdu1212 Big Number &amp;第六届山东省赛Single Round Math (同余定理,大数取模)

题目链接:Big Number 题目大意:每次输入两个数,第一个是高精度,第二个数小于100000:求 a mod b 根据同余定理: (a+b)% c = (a%c+ b%c)%c (a*b)%c =  ( a%c* b%c)%c 所以 对于大数,例如 :123 可以这样分解 123 =  (1*10+2)*10 + 3: 123 % c =   (  (  (  1%c *  10%c)%c + 2%c) %c  * 10%c) + 3 %c  ) %c; 因此,我们用字符串处理这个数,通过

郑轻第六届校赛 -- 部分题解

1427: 数字转换 Time Limit: 1 Sec  Memory Limit: 128 MB Submit: 379  Solved: 93 SubmitStatusWeb Board Description 老师交给小明一个任务,有两个数字x和y(x<y),通过以下两种操作:一.将x乘以2:二.将x的值加上1.小明希望能通过尽可能少的操作来完成这个任务,但是不知道怎么做,现在请大家来帮帮他的忙吧. Input 两个整数x,y(0<=x<y<=10^6). Output 一

NYOJ-682 小媛在努力 (郑大第六届校赛 模拟)

链接:click here 题意: 描述 在多媒体数据处理中,数据压缩算法尤为重要.小媛上完课后就想自己发明一个数据压缩算法.她想呀想,终于想到一个方法.在多媒体数据中有很多数据都是重复的,所以她想把连续相同的数据用数据出现的次数和数据本身表示.例如:1 1 1 2 3 3 3 3 3  压缩后及为3 1 1 2 5 3(表示3个1,1个2和5个3).有想法后小媛就希望把它用代码实现了.但是大家都知道小媛现在整天都忙着苦B的复习考研,连电脑都摸不到.所以她希望作为ACMer的你帮她写一下. 输入

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

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组测试数据,每个数据占一行,仅包含一个正整

第六届湘潭市程序设计竞赛 -Happy Number

Happy Number Accepted : 110   Submit : 263 Time Limit : 1000 MS   Memory Limit : 65536 KB  Problem Description Recently, Mr. Xie learn the concept of happy number. A happy number is a number contain all digit 7 or only 1 digit other than 7. For examp

湖南省第六届 中信软件教育杯 ???学生程序设计大赛试题 第三题 数字整除

http://www.baidu.com/ 对于每组测试数据,输出一行,表示相应的n是否是17的倍数.1表示是,0表示否. Sample Input 34 201 2098765413 1717171717171717171717171717171717171717171717171718 0 Sample Output 1 0 1 0 Problem Source The Sixth Hunan Collegiate Programming Contest 题目连接:http://acm.hu