码迷,mamicode.com
首页 > 其他好文 > 详细

UVA11882 Biggest Number 强剪枝

时间:2015-08-02 18:24:09      阅读:115      评论:0      收藏:0      [点我收藏+]

标签:c++

题目链接:

UVA11882




解题思路:

常规思路是 枚举每个点,暴力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;
}



版权声明:本文为博主原创文章,未经博主允许不得转载。

UVA11882 Biggest Number 强剪枝

标签:c++

原文地址:http://blog.csdn.net/axuan_k/article/details/47208365

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!