首页 > 代码库 > UVa11882,Biggest Number

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;    }}
View Code