UVA-11882 Biggest Number (DFS+剪枝)

题目大意:给出一个方格矩阵,矩阵中有数字0~9,任选一个格子为起点,将走过的数字连起来构成一个数,找出最大的那个数,每个格子只能走一次。

题目分析:DFS。剪枝方案:在当前的处境下,找出所有还能到达的点的个数,若当前数字的长度加上个数仍小于目前最优答案的长度,则剪去;若长度相等,则将所有还能到达的数字按从大到小排序后连到当前数字上,如果还比目前最优解小,则减去。找出所有还能到达的点的过程用BFS实现。

代码如下:

# include<iostream>
# include<cstdio>
# include<queue>
# include<string>
# include<cstring>
# include<algorithm>
using namespace std;
string ans;
int r,c,vis[35][35],mark[35][35],v[1000];
char p[35][35];
int d[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
bool ok(int x,int y)
{
    if(x>=0&&x<r&&y>=0&&y<c)
        return true;
    return false;
}
bool smaller(string a,string b)
{
    if(a.size()<b.size())
        return true;
    if(a.size()==b.size()&&a<b)
        return true;
    return false;
}
int bfs(int x,int y)
{
    queue<int>q;
    memset(mark,0,sizeof(mark));
    q.push(x*c+y);
    mark[x][y]=1;
    int res=0;
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        for(int i=0;i<4;++i){
            int nx=u/c+d[i][0],ny=(u%c)+d[i][1];
            if(ok(nx,ny)&&p[nx][ny]!=‘#‘&&!vis[nx][ny]&&!mark[nx][ny]){
                mark[nx][ny]=1;
                v[res++]=p[nx][ny]-‘0‘;
                q.push(nx*c+ny);
            }
        }
    }
    return res;
}
void dfs(int x,int y,string ap)
{
    if(smaller(ans,ap))
        ans=ap;
    else{
        int len=bfs(x,y);
        if(ap.size()+len<ans.size())
            return ;
        if(ap.size()+len==ans.size()){
            sort(v,v+len);
            string app=ap;
            for(int i=len-1;i>=0;--i)
                app+=char(v[i]+‘0‘);
            if(smaller(app,ans))
                return ;
        }
    }
    for(int i=0;i<4;++i){
        int nx=x+d[i][0],ny=y+d[i][1];
        if(ok(nx,ny)&&p[nx][ny]!=‘#‘&&!vis[nx][ny]){
            vis[nx][ny]=1;
            dfs(nx,ny,ap+p[nx][ny]);
            vis[nx][ny]=0;
        }
    }
}
void solve()
{
    for(int i=0;i<r;++i){
        for(int j=0;j<c;++j){
            if(p[i][j]!=‘#‘){
                memset(vis,0,sizeof(vis));
                vis[i][j]=1;
                string ap="";
                ap+=p[i][j];
                dfs(i,j,ap);
            }
        }
    }
    cout<<ans<<endl;
}
int main()
{
    while(scanf("%d%d",&r,&c)&&r+c)
    {
        ans.clear();
        for(int i=0;i<r;++i)
            scanf("%s",p[i]);
        solve();
    }
    return 0;
}

  

时间: 2024-10-14 13:56:29

UVA-11882 Biggest Number (DFS+剪枝)的相关文章

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

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

UVA 11882 Biggest Number 深搜 剪枝

如图,给一个图,每个格子只能走一次,起点终点任意,求按路径顺序将格子里的数字拼在一起,最大的数字. 很容易想到用暴力求解的方法,但最多会有 30 个格子,O(2^30) 肯定超时了. 考虑剪枝,设当前已经找到一个 ans,若当前路径的最大长度小于 ans 的长度,则不可能比 ans 大,剪掉, 若等于,则考虑当前路径已经形成的数字(假设 n 位),若小于 ans 的前 n 位,则剪掉. 代码: #include <iostream> #include <cstring> #incl

UVa11882 Biggest Number (DFS+剪枝)

链接:http://vjudge.net/problem/23314 分析:两种剪枝方案. 1.找出在当前位置下还能够到达的点的个数(尽管实际能到达的点的个数比它小,但乐观估计就可以了),若当前数字加上个数仍小于目前最优解的长度,则剪枝. 2.若将还能够到达的数字按从小到大连接到当前数字后面,若仍比目前最优解小,则剪枝.(找出所有还能够到达的点用BFS实现(乐观估计)). 1 #include <cstdio> 2 #include <algorithm> 3 #include &

UVA 10318 - Security Panel dfs 剪枝

UVA 10318 - Security Panel dfs 剪枝 ACM 题目地址:UVA 10318 - Security Panel 题意: 这题跟点灯的题目很像,点灯游戏选择一盏灯时会让它以及四周的灯改变状态. 但是我们有特殊的开开关技巧,它给出了改变状态的位置,而不是四周都改变. 问你从全部关着变成全部开着的最小开关步骤. 分析: 很明显,在一个位置上点两次或更多次是没有必要的,所以一个位置只有选择与不选择,用dfs即可,但如果暴力所有可能,复杂度是2^25,会超时,所以要剪枝. 由于

湖南省第六届省赛题 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 neighb

【UVa】Biggest Number(dfs+剪枝)

题目 题目 ? ? 分析 典型搜索,考虑剪枝. 统计一下联通分量. 1.本位置能够达到所有的点的数量加上本已有的点,还没有之前的结果长,直接返回. 2.当本位置能够达到所有的点的数量加上本已有的点与之前的结果一样长,就把联通分量里的点从大到小排序.如果这样都比Ans小,那么直接返回. 前两种是大多人用的,这两个剪枝有了,AC不是问题. 3.如果本图没有障碍物,那么意味着所有点联通,那么结果必定是从整张图的最大值出发的,非最大值,就不用考虑了. 这个是我自己想的,大约能剪 40-80 ms. 个人

UVa 208 消防车(dfs+剪枝)

https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=144 题意:给出一个n个结点的无向图以及某个结点k,按照字典序从小到大顺序输出从1到结点k的所有路径. 思路:如果直接矩阵深搜的话是会超时的,所以我们可以从终点出发,将与终点相连的连通块保存起来,这样dfs深搜时可以剪枝掉一些到达不了的点.只要解决了这个,dfs就是小问题. 这道题还有点坑的

UVA11882 Biggest Number 强剪枝

题目链接: UVA11882 解题思路: 常规思路是 枚举每个点,暴力dfs,然后选择最大的那个  但题目只给了1000MS 这就需要剪枝了 剪枝1: 假设当前答案长度为ans,那么当我们走到一个点(x, y)的时候,bfs一下判断能接触的格子数.假设现在能从(x, y)走到的点,我们都能到达,这是最好的情况.设从(x, y)能走到的点数为maxlen,那么如果从出发点走到(x, y)经过的格子,加上maxlen,都没有ans的长度大,那么不管从(x, y)怎么搜,我们都不能取代我们现在的ans

uva 219 - Department of Redundancy Department(dfs+剪枝)

题目链接:uva 219 - Department of Redundancy Department 题目大意:给定一些关系,问哪一些关系是可以被替代的,如果可以被替代,给出替代的方案,一种即可. 解题思路:因为总共也就26个字母,所以用二进制数表示状态.剪枝,每次将所有可选关系均考虑进去都无法满足则是false. #include <cstdio> #include <cstring> #include <algorithm> using namespace std;

UVa11882,Biggest Number

搜索+剪枝 如此水的一个题,居然搞了一上午 出错在bfs与dfs时共用了一个vis数组,导致bfs完后返回dfs应该能访问到的点访问不到 自己想怎么剪枝,想了几个剪枝方法,又证明,又推翻,再想,再证明,再推翻用了好长时间T T自己还是水的不行啊 两个剪枝: 1.若,当前求出来的解now的长度+当前状态下从now节点(因为可能有多个连通块,用vis[]判断未访问到的节点是不行的)开始能访问到的节点的个数(bfs遍历即可)<当然ans的长度,那么剪枝.这样大概能减掉一半的枝叶.但是可能还会超时 2.