1. 程式人生 > >【UVa】Biggest Number(dfs+剪枝)

【UVa】Biggest Number(dfs+剪枝)

scanf sin ret break puts 從大到小 如果 ssl ges

題目

題目
?


?

分析

典型搜索,考慮剪枝。
統計一下聯通分量。

  • 1、本位置能夠達到所有的點的數量加上本已有的點,還沒有之前的結果長,直接返回。

  • 2、當本位置能夠達到所有的點的數量加上本已有的點與之前的結果一樣長,就把聯通分量裏的點從大到小排序。如果這樣都比Ans小,那麽直接返回。

前兩種是大多人用的,這兩個剪枝有了,AC不是問題。

  • 3、如果本圖沒有障礙物,那麽意味著所有點聯通,那麽結果必定是從整張圖的最大值出發的,非最大值,就不用考慮了。
    這個是我自己想的,大約能剪 40-80 ms。

個人覺得本題較坑,一開始我判聯通分量用的是dfs,瘋狂Tle。。。改成bfs 460ms。再瞎搞剪到400ms。

這個速度不算快,我覺得是我常數太大了,或者寫法不太好。
?


?

代碼

#include <cstring>
#include <queue>
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
int r,c,L,num;
int vis[33][33],vis2[33][33];
int dx[5]={1,-1,0,0},dy[5]={0,0,1,-1};

vector<char> Ans,v;
char map[33][33
]; bool cmp(int x,int y){ return x>y; } bool in(int x,int y) { if(x>=0 && x<r && y>=0 && y<c) return true; return false; } void GetNum(int sx,int sy) { memset(vis2,0,sizeof(vis2)); v.clear(); queue<int> q; q.push(sx*33+sy); while(!q.empty()) { int
m=q.front(); q.pop(); int x=m/33,y=m%33; for(int i=0;i<4;i++) { int px=x+dx[i],py=y+dy[i]; if(in(px,py) && map[px][py]!='#' && !vis[px][py] && !vis2[px][py]) { v.push_back(map[px][py]); vis2[px][py]=1; q.push(px*33+py); } } } L=v.size(); } int small(vector<char> a,vector<char> b) { for(int i=0;i<min(a.size(),b.size());i++) { if(a[i] < b[i]) return 1; if(a[i] > b[i]) return 0; } return 2; } void dfs(int x,int y,vector<char> S) { if(((small(S,Ans)==0 && S.size() == Ans.size()) && S.size()) || S.size() > Ans.size()) Ans=S; GetNum(x,y); if(S.size() + L < Ans.size()) return; if(S.size() + L == Ans.size()) { int q=small(S,Ans); if(q==1) return; if(q==0) goto l1; sort(v.begin(),v.end(),cmp); int f=0; for(int i=0;i<L;i++) { if(v[i] < Ans[i+S.size()]) { f=1; break; } if(v[i] > Ans[i+S.size()]) break; } if(f==1) return; } l1: for(int i=0;i<4;i++) { int px=x+dx[i],py=y+dy[i]; if(in(px,py) && map[px][py]!='#' && !vis[px][py]) { vis[px][py]=1; S.push_back(map[px][py]); dfs(px,py,S); vis[px][py]=0; S.pop_back(); } } } int main() { while(scanf("%d%d",&r,&c)==2 && r && c) { int num=0,maxnum=-1; Ans.clear(); v.clear(); memset(vis,0,sizeof(vis)); for(int i=0;i<r;i++) { scanf("%s",map[i]); for(int j=0;j<c;j++) if(map[i][j]=='#') num++; else maxnum=max(maxnum,map[i][j]-'0'); } for(int i=0;i<r;i++) { for(int j=0;j<c;j++) { vector<char> S; if(map[i][j]!='#') { if(num==0 ) if(map[i][j]<maxnum+'0') continue; vis[i][j]=1; S.push_back(map[i][j]); dfs(i,j,S); vis[i][j]=0; } } } for(int i=0;i<Ans.size();i++) printf("%c",Ans[i]); puts(""); } return 0; }

【UVa】Biggest Number(dfs+剪枝)