标签:c++
题目链接:
解题思路:
常规思路是 枚举每个点,暴力dfs,然后选择最大的那个 但题目只给了1000MS 这就需要剪枝了
剪枝1:
假设当前答案长度为ans,那么当我们走到一个点(x, y)的时候,bfs一下判断能接触的格子数。假设现在能从(x, y)走到的点,我们都能到达,这是最好的情况。设从(x, y)能走到的点数为maxlen,那么如果从出发点走到(x, y)经过的格子,加上maxlen,都没有ans的长度大,那么不管从(x, y)怎么搜,我们都不能取代我们现在的ans(长才是王道懂不懂),那么直接回溯,不要这个点了。这个剪枝效力还是不错的。
而如果等于的话 我们需要一个标记 flag 来表示当前串和 ans串的大小关系
剪枝2: 如果ans串已经是最大可能长度 且搜索的起点小于ans串的起点 则直接跳过
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<queue> #include<time.h> #define printime printf("%.3lf\n",(double)clock() / CLOCKS_PER_SEC) #define maxn 33 using namespace std; struct node{ int x,y; }que[10050],u; char ans[maxn],temp[maxn]; int dir[4][2]={1,0,-1,0,0,1,0,-1}; char map[maxn][maxn]; char g[maxn][maxn]; int sum; int max_len; int n,m; int ok(int x,int y) { if(x<1||y<1||x>n||y>m) return 0; return 1; } int bfs(int x,int y) { for(int i=1;i<=n;i++) strcpy(g[i]+1,map[i]+1); int head=0,tail=0; int tx,ty; que[tail++]=(node){x,y}; while(head<tail) { u=que[head++]; for(int i=0;i<4;i++) { tx=u.x+dir[i][0]; ty=u.y+dir[i][1]; if(!ok(tx,ty)||g[tx][ty]=='#') continue; g[tx][ty]='#'; que[tail++]=(node){tx,ty}; } } return head; } int flag; void dfs(int x,int y,int len) { if(len>max_len||(len==max_len&&flag==1)) { max_len=len; temp[len]='\0'; strcpy(ans,temp); flag=0; //一个起点得到新的ans串 需要继续比较 } // printf("x=%d y=%d len=%d flag=%d\n",x,y,len,flag); int res=bfs(x,y); if(len+res-1<max_len||(len+res-1==max_len&&flag==-1)) //剪枝1 return; int tx,ty; for(int i=0;i<4;i++) { tx=x+dir[i][0]; ty=y+dir[i][1]; if(!ok(tx,ty)||map[tx][ty]=='#') continue; temp[len]=map[tx][ty]; map[tx][ty]='#'; if(flag==0){ if(temp[len]<ans[len]) flag=-1; else if(temp[len]>ans[len]) flag=1; dfs(tx,ty,len+1); flag=0; //回溯 } else dfs(tx,ty,len+1); map[tx][ty]=temp[len]; } } int main() { // freopen("in.txt","r",stdin); while(scanf("%d%d",&n,&m)&&(m+n)) { sum=0; max_len=0; memset(ans,'\0',sizeof(ans)); memset(temp,'\0',sizeof(temp)); for(int i=1;i<=n;i++){ scanf("%s",map[i]+1); for(int j=1;j<=m;j++) if(map[i][j]!='#') sum++; } for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) { if(map[i][j]!='#') { if(max_len==sum&&map[i][j]<ans[0]) //剪枝2 continue; temp[0]=map[i][j]; map[i][j]='#'; if(ans[0]==temp[0]) flag=0; else if(temp[0]>ans[0]) flag=1; else flag=-1; dfs(i,j,1); map[i][j]=temp[0]; } } printf("%s\n",ans); // printime; } return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:c++
原文地址:http://blog.csdn.net/axuan_k/article/details/47208365