UVa11882,Biggest Number

搜索+剪枝

如此水的一个题,居然搞了一上午

出错在bfs与dfs时共用了一个vis数组,导致bfs完后返回dfs应该能访问到的点访问不到

自己想怎么剪枝,想了几个剪枝方法,又证明,又推翻,再想,再证明,再推翻用了好长时间T T自己还是水的不行啊

两个剪枝:

1.若,当前求出来的解now的长度+当前状态下从now节点(因为可能有多个连通块,用vis[]判断未访问到的节点是不行的)开始能访问到的节点的个数(bfs遍历即可)<当然ans的长度,那么剪枝。这样大概能减掉一半的枝叶。但是可能还会超时

2.在剪枝1的条件下,若==呢?剪枝1时bfs的时候存下所以当前状态下能访问到的点,对这些点降序排序然后接到now后面,那么得到的就是当前状态下可能搜到的最优解,若该解仍小于ans,那么剪枝。又能减掉一大半的枝叶。

总结:

  这题虽然花了我不少时间,但是也能总结出不少东西。

  剪枝时若当前状态下可能得到的最优解仍然小于ans,那么就可以剪枝。

  这可能就是所谓的最优化剪枝吧。

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <vector>
using namespace std;
int r,c,map[20][20],vis[20][20],d[40][2],dtop,ans,f[20][20],maxlen,cc;
int dx[]={0,0,1,-1},dy[]={1,-1,0,0};
vector<int> cnt;
struct Node{
    int x,y,len;
};
int init(){
    memset(vis,0,sizeof(vis));
    memset(map,0,sizeof(map));
    dtop=0;
    char ch;
    for (int i=0;i<r;i++)
        for (int j=0;j<c;j++){
            cin>>ch;
            if (ch==‘#‘) map[i][j]=-1;
                else {map[i][j]=ch-‘0‘;d[dtop][0]=i;d[dtop][1]=j;dtop++;}
        }
}
int ok(int x,int y){
    if (x>=0&&y>=0&&x<r&&y<c) return 1;
    return 0;
}
int len(int s){
    return (log10(s)+1.5);
}
int bfs(int x,int y){
    int len=0;
    queue<Node>  q;
    Node u;
    int bv[20][20];
    for (int i=0;i<r;i++)
        for (int j=0;j<c;j++)
            bv[i][j]=vis[i][j];
    u.x=x;u.y=y;u.len=1;
    q.push(u);
    while (!q.empty()){
        u=q.front();
        for (int i=0;i<4;i++){
            Node v;
            v.x=u.x+dx[i];v.y=u.y+dy[i];v.len=u.len+1;
            if (ok(v.x,v.y)&&!bv[v.x][v.y]&&map[v.x][v.y]>0){
                bv[v.x][v.y]=1;
                len++;
                cnt.push_back(map[v.x][v.y]);
                q.push(v);
            }
        }
        q.pop();
    }
    return len;
}
int sum(int s){
    sort(cnt.begin(),cnt.end(),greater<int>());
    for (int i=0;i<cnt.size();i++)
        s=s*10+cnt[i];
    return s;
}
int dfs(int x,int y,int s){
    s=s*10+map[x][y];
    cc++;
    cnt.clear();
    if (ans){
        int l=bfs(x,y);
        int t=len(s)+l;
        if ((len(s)+l)<len(ans)) return 0;
        if ((len(s)+l)==len(ans)&&sum(s)<ans) return 0;
    }
    int nextx,nexty;
    for (int i=0;i<4;i++){
        nextx=x+dx[i];nexty=y+dy[i];
        if (ok(nextx,nexty)&&!vis[nextx][nexty]&&map[nextx][nexty]>0){
            vis[nextx][nexty]=1;
            dfs(nextx,nexty,s);
            vis[nextx][nexty]=0;
        }
    }
    ans=max(ans,s);
    return 1;
}
int main(){
    while (cin>>r>>c&&r&&c){
        init();
        ans=0;
        maxlen=0;
        /*
for (int k=0;k<dtop;k++){
            memset(vis,0,sizeof(vis));
            vis[d[k][0]][d[k][1]]=1;
            f[d[k][0]][d[k][1]]=bfs(d[k][0],d[k][1]);
        }*/
        for (int k=0;k<dtop;k++){
            memset(vis,0,sizeof(vis));
            vis[d[k][0]][d[k][1]]=1;
            dfs(d[k][0],d[k][1],0);
        }
        cout<<ans<<endl;
    }
}

UVa11882,Biggest Number

时间: 2024-10-21 21:18:52

UVa11882,Biggest Number的相关文章

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

UVA11882 Biggest Number 强剪枝

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

UVA-11882 Biggest Number (DFS+剪枝)

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

UVa11882 Biggest Number (DFS+剪枝)

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

serial number 配置, product, serial number master data, equipment, function location

1: 首先定义 serial number 的处理流程,在SRVC item 中serial number 是否必须. SPRO> define serial number profiles 2: 添加一个 serial number profile: new entry 3:  创建 profile, 填写属性,包括一致性检查等.保存 4: 填写profile的 procedure 5:定义procedure序列,每个序列对应不同的transaction 配置serial number 是否是

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

【UVa】Biggest Number(dfs+剪枝)

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

如果参数number包含Null,则返回Null;如果参数character包含Null

VBA字符串处理大全 1 VBA中的字符串2 VBA中处理字符串的函数2.1 比较字符串2.2 转换字符串2.3 创建字符串2.4 获取字符串的长度2.5 格式化字符串2.6 查找字符串2.7 提取字符/字符串2.8 删除空格2.9 返回字符代码2.10 返回数值代表的相应字符2.11 使用字节的函数2.12 返回数组的函数2.13 连接字符串2.14 替换字符串2.15 反向字符串==================================================== 1 VB