Biggest Number(回溯/bfs/剪枝)

本文介绍了如何使用深度优先搜索(DFS)和广度优先搜索(BFS)结合剪枝策略解决UVA11882题目中的寻找最大数字问题,通过字符串操作优化比较过程,展示了动态更新和剪枝技巧在优化解题效率中的关键作用。
摘要由CSDN通过智能技术生成

Biggest Number

题意

Biggest Number - UVA 11882 - Virtual Judge (vjudge.net)

寻找最大的数。

思路

dfs(回溯)+剪枝(bfs).由于string的大小比较和本题数字的大小比较类似,所以用string更方便。每一次dfs时要考虑当前节点之后所能串起来的数的个数,分为三种情况:1,数的个数太少,显然不满足,跳过当前的节点的dfs(剪枝);2,数的个数+当前的长度now能跟之前一样长,那就比较ans的子字符串跟当前的now字符串谁大,如果ans大那就没必要继续(剪枝);3,数的个数+当前now的长度比ans的长度更长,那就显然拼接后的更大,要及时更新。

int r,c;
int vis[maxn][maxn],visb[maxn][maxn];
string a[maxn],ans;
int v[][2]={{-1,0},{1,0},{0,-1},{0,1}};
struct node{
    int x,y;
};
void update(string now) {
    if(ans.size()<now.size() || (ans.size()==now.size() && ans<now)) ans=now;
}
bool in_area(int x,int y) {
    return x>=0 && x<r && y>=0 && y<c;
}
int bfs(int x,int y) {
    int relax=0;
    queue<node> q;
    q.push({x,y});
    memcpy(visb,vis,sizeof vis);
    visb[x][y]=1;
    while (!q.empty()) {
        x=q.front().x,y=q.front().y;
        q.pop();
        for(int i=0;i<4;i++) {
            int xi=x+v[i][0],yi=y+v[i][1];
            if(!in_area(xi,yi)) continue;

            if(!visb[xi][yi]) {
                visb[xi][yi]=1;
                if(a[xi][yi]=='#') continue;
                q.push({xi,yi});
                relax++;
            }
        }
    }
    return relax;

}
void dfs(int x,int y,string now) {
    int relax=bfs(x,y),sz=(int)now.size(),asz=(int)ans.size();
    if(sz+relax<asz) return ;
    if(ans.substr(0,sz)>now && sz+relax==asz) return ;
    update(now);
    for(int i=0;i<4;i++) {
        int xi=x+v[i][0],yi=y+v[i][1];
        if(!in_area(xi,yi)) continue;

        if(!vis[xi][yi] && a[xi][yi]!='#') {
            vis[xi][yi]=1;
            if(a[xi][yi]=='#') continue;
            dfs(xi,yi,now+a[xi][yi]);
            vis[xi][yi]=0;
        }
    }

}
int main(int argc, char const *argv[]) {
    while (~scanf("%d%d",&r,&c)&&r) {
        ans="";
        qwe(i,0,r-1) cin>>a[i];

        qwe(i,0,r-1) {
            qwe(j,0,c-1) {
                if(a[i][j]=='#') continue;
                mem(vis,0);
                vis[i][j]=1;
                string now;
                now=a[i][j];
                dfs(i,j,now); // 初始值不要忘
            }
        }
    
        std::cout << ans << '\n';
    }
    return 0;

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值