hdu 3812 Sea Sky 深搜+剪枝

题目意思:

从sea 找一条道sky 的最长路

题解:

先进行一系列的预处理

1。将所有不重复的字符串先保留下来,然后从小到大排序,这样深搜的时候最先弄出来的答案就是最小的 字母序。

2. 进行深度优先搜索保留答案

3. 剪枝:

(1) 要注意sea sky 不存在的情况

(2) 要主要不连通情况

(3) 强力剪枝 不解释了。


#include<cstdio>
#include<cstring>
#include<iostream>
#include<string>
#include<map>
#include<algorithm>
using namespace std;
char real[105][30];
int n,w=0,mm[105][105],st,et;
char temp1[208][30];
int record[105],vis[105],vis1[105];
int yes[105],root[105];

int Find(int r)
{
    if(r==root[r]) return r;
    else return root[r]=Find(root[r]);
}

int add(char *a)
{
    int i;
    for(i=0;i<w;i++){
        if(strcmp(a,real[i])==0)
         return i;
    }
    strcpy(real[w++],a);
}
void init()
{
    int i,num=0,j;
    char s1[30],s2[30];

    for(i=0;i<n;i++){
        scanf("%s %s",s1,s2);
        add(s1);
        add(s2);
        strcpy(temp1[num++],s1);
        strcpy(temp1[num++],s2);
    }
    for(i=0;i<w-1;i++)
        for(j=i+1;j<w;j++){
            if(strcmp(real[i],real[j])>0){
                char temp[30];
                strcpy(temp,real[j]);
                strcpy(real[j],real[i]);
                strcpy(real[i],temp);
            }
        }
        for(i=0;i<w;i++) root[i]=i;
    for(i=0;i<num;i+=2){
        int nowx=add(temp1[i]),nowy=add(temp1[i+1]);
        mm[nowx][nowy]=mm[nowy][nowx]=1;
        int ra=Find(nowx),rb=Find(nowy);
        if(ra!=rb) root[rb]=ra;
    }

}
int ansl=0;
int dfs(int now,int tt)
{
	if(tt>=w) return 0;
    int i;
    vis[now]=1;
    record[tt]=now;
    if(now==et){
        if(ansl<tt) {
            ansl=tt;
            for(i=0;i<=ansl;i++) yes[i]=record[i];
        }
			if(tt==w-1) return 1;
    }
    for(i=0;i<w;i++){
        if(vis[i]==0&&mm[now][i]==1){
            vis[i]=1;
            if(dfs(i,tt+1)) return 1;
            vis[i]=0;
        }
    }
	return 0;
}

int dfs1(int ttt,int ending)
{
    int i;
    if(ttt==ending) return 1;
    for(i=0;i<w;i++){
        if(!vis1[i]&&mm[ttt][i]&&(!vis[i])){
            vis1[i]=1;
            if(dfs1(i,ending)) return 1;
            //vis1[i]=0;
        }
    }
    return 0;
}
int main()
{
    int i,cc,Case=0;
    scanf("%d",&cc);
    while(cc--){
        Case++;
        scanf("%d",&n);
        memset(vis,0,sizeof(vis));
        memset(mm,0,sizeof(mm));
        w=0;
        init();
        st=-1;et=-1;

        for(i=0;i<w;i++){
            if(strcmp(real[i],"sea")==0) st=i;
            if(strcmp(real[i],"sky")==0) et=i;
        }
        printf("Case %d:",Case);
        if(st==-1||et==-1){
            printf(" what a pity\n");
            continue;
        }
        if(Find(st)!=Find(et)) {
            printf(" what a pity\n");
            continue;
        }
        for(i=0;i<w;i++){
            memset(vis1,0,sizeof(vis1));
            vis1[st]=1;
            if(!dfs1(i,et)) vis[i]=1;
        }
        for(i=0;i<w;i++){
            memset(vis1,0,sizeof(vis1));
            vis1[et]=1;
            if(!dfs1(i,st)) vis[i]=1;
        }
        ansl=0;
        dfs(st,0);

        for(i=0;i<=ansl;i++){
            printf(" %s",real[yes[i]]);
        }
        printf("\n");
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值