UVA 11882 Biggest Number (搜索+剪枝(dfs+bfs))

22 篇文章 0 订阅
18 篇文章 0 订阅
该博客讨论了一种矩阵问题,其中包含数字和障碍物。任务是从矩阵中的任一数字开始,沿上下左右移动,避开障碍物且不重复经过任何数字,形成一个数字序列。目标是找到能构成的最大整数。博主提出通过深度优先搜索(DFS)并结合剪枝策略来解决,当当前位置剩余可走的最大长度加上已走长度小于当前最优解时终止搜索。
摘要由CSDN通过智能技术生成


题意:在一个R行C列 (2R,C15,RC30) 的矩阵里有障碍物和数字格(包含1~9的数字)。你可以从任意一个数字格出发,每次沿着上下左右之一的方向走一格,但不能走到障碍格中,也不能重复经过一个数字格,然后把沿途经过的所有数字连起来,如图所示。如图可以得到9784,4832145等整数。问:能得到的最大整数是多少?(本段摘自《算法竞赛入门经典(第2版)》)

最大的数示意图

分析:
枚举起点进行DFS即可。有一个最优性剪枝,即当当前位置的时候,剩下可以走的最大长度加上已走长度如果仍然小于当前最优的答案时,直接return,如果相等但是字典序比当前最优答案小的话也直接return。

#include<bits/stdc++.h>
using namespace std;
char s[22][22];
int vis[22][22],vis1[22][22],a[33];
int dx[]={-1,0,1,0};
int dy[]={0,1,0,-1};
int n,m;
struct P
{
    int x,y;
    P(int x,int y):x(x),y(y){}
    P(){}
};
string ans;
int bfs(int x,int y)
{
    int i,j,tx,ty,len=0;
    queue<P>que;
    que.push(P(x,y));
    vis1[x][y]=1;
    while(!que.empty()) {
        P p = que.front();
        que.pop();
        for(i=0;i<4;i++) {
            tx=p.x+dx[i];
            ty=p.y+dy[i];
            if(tx<0||tx>=n||ty<0||ty>=m||vis[tx][ty]||vis1[tx][ty]||s[tx][ty]=='#') continue;
            vis1[tx][ty]=1;
            a[len++]=s[tx][ty]-'0';
            que.push(P(tx,ty));
        }
    }
    return len;
}
void dfs(int x,int y,string tmp)
{
    int i,j,tx,ty;
   // cout<<tmp<<endl;
   / 剪枝
    if(tmp.length()>ans.length()||(tmp.length()==ans.length() && tmp>ans)) ans=tmp;
    else {
        memset(vis1,0,sizeof(vis1));
        int len = bfs(x,y);
        if(ans.length()>tmp.length()+len) return;
        sort(a,a+len,greater<int>());
        string t = tmp;
        for(i=0;i<len;i++) {
            t+=char(a[i]+'0');
        }
        if(ans.length()==t.length() && ans>t) return ;
    }
    
     剪枝
    
    for(i=0;i<4;i++) {
        tx=x+dx[i],ty=y+dy[i];
        if(tx<0||tx>=n||ty<0||ty>=m||vis[tx][ty]||s[tx][ty]=='#') continue;
        vis[tx][ty] = 1;
        dfs(tx,ty,tmp+s[tx][ty]);
        vis[tx][ty]=0;
    }
}
int main()
{
    int i,j;
    string tmp;
    ios::sync_with_stdio(false);
    while(cin>>n>>m) {
        if(n==0 && m==0) break;
        for(i=0;i<n;i++) cin>>s[i];
        ans="";
        for(i=0;i<n;i++) {
            for(j=0;j<m;j++) {
                tmp="";
                if(s[i][j]=='#') continue;
                vis[i][j]=1;
                dfs(i,j,tmp+s[i][j]);
                vis[i][j]=0;
            }
        }
        cout<<ans<<endl;
    }
    return 0;
}










  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值