搜索+剪枝
如此水的一个题,居然搞了一上午
出错在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