2017暑假集训 div1 搜索进阶(1)

来源:互联网 发布:最优化方法推荐 编辑:程序博客网 时间:2024/06/06 01:11

HDU 1560 (IDA*)

题意:给少于八个的DNA序列,问使 DNA 序列为其子串的序列最短多长?

做法:第一次做这种迭代加深搜的题,就看了大牛们的博客。

说说我的理解把:深搜之所以效率不高是因为它是一种盲目的搜索(俗称一路走到黑)。那么如果我们限制它说能走到的层数,如果在该层没有找到,加层数加一接着向下找,就会节省时间。

1.首先取所有子串中最长的为初始深度

2.做 DFS  剪枝 (1).如果当前层数超越限制层数

                         (2).用f(h)函数来估计最佳情况,那么h就是 当前的长度 加上 所有串中剩余最多的长度。 进入剪枝1

3. 如果没有满足题意,限制深度++,重复2操作!

注意:这里的状态开了个8的数组表示每个串匹配到什么位置。 


代码:

#include <iostream>#include <stdio.h>#include <algorithm>#include <string.h>#include <queue>using namespace std;char str[10][10];char dna[4]={'A','C','G','T' };int ans, n,deep=0;void dfs(int now,int len[10]){   if(now>deep) return;   int h=0;   for(int i=0;i<n;++i)   {       int temp= strlen(str[i])-len[i];       h=max(h,temp);   }   if(h==0) { ans=now; return ;}   if(h+now>deep) return ;   for(int i=0;i<4;++i)   {      bool flag=0;  int pos[10]={0};      for(int j=0;j<n;++j)      {          if(str[j][len[j]]==dna[i])          {              flag=1;  pos[j]=len[j]+1;          }          else pos[j]=len[j];      }        if(flag) dfs(now+1,pos);        if(ans!=-1) return;   }}int main(){    int T;    scanf("%d",&T);    while(T--)    {        deep=0; ans=-1;        scanf("%d",&n);        for(int i=0;i<n;++i)        {            scanf("%s",str[i]);            int temp=strlen(str[i]);            deep=max(deep,temp);        }        int pos[10]={0};        while(1)        {            dfs(0,pos);            if(ans!=-1) break;            deep++;        }        printf("%d\n",ans);    }    return 0;}


  

HDU 3085 双向BFS 

题意: 输入n*m的字符矩阵,矩阵中的 M 速度 是3格/m, G的速度是1格/m,Z是鬼,初始有两个,每秒可以变出很多的分身Z(变出的分身在下一秒钟仍然可以变出无数个分身),占领跟Z距离是2的方格,直到占领所有的方格,每次都是鬼先占领方格,然后是M跟G走,M跟G可以同时都走,也可以有一个在原地不动,一个在走。


做法:解锁了新姿势原来做BFS的时候都是一条路走到黑没有讨论过天数。

关键:每次调用BFS先用size存下原来队列里的节点个数,每次拓展的时候把这些节点弹完就结束

1.M 每次走三步 就BFS三天即可 ,G 走一步 就BFS一遍即可

2.判断鬼因为可以穿墙所以直接用 当前点与鬼的距离(X+Y )与 2*time 的关系即可判断

代码:

#include <iostream>#include <stdio.h>#include <string.h>#include <algorithm>#include <queue>#include <math.h>using namespace std;struct node{    int x,y;}z[2],mm,gg;char map[805][805];int n,m;bool vis[2][805][805];queue<node>  q[2];int step=0;int dir[4][2]={1,0, -1,0, 0,-1, 0,1 };int judge(struct node a){   if(a.x<0||a.x>=n||a.y<0||a.y>=m) return 0;   if(  map[a.x][a.y]=='X' ) return 0;   if( (abs(z[0].x-a.x)+abs(z[0].y-a.y))<=2*step ) return 0;   if( (abs(z[1].x-a.x)+abs(z[1].y-a.y))<=2*step ) return 0;   return 1;}int bfs(int w){    node u,v;    int sum=q[w].size();    while(sum--)    {        u=q[w].front(); q[w].pop();        if(judge(u)==0) continue;        for(int i=0;i<4;++i)        {            v.x=u.x+dir[i][0];            v.y=u.y+dir[i][1];            if(judge(v)==0) continue;            if(!vis[w][v.x][v.y])            {                if(vis[w^1][v.x][v.y]) return 1;                vis[w][v.x][v.y]=1;                q[w].push(v);            }        }    }    return 0;}int work(){    while(!q[0].empty()) q[0].pop();    while(!q[1].empty()) q[1].pop();    memset(vis,0,sizeof(vis));    q[0].push(mm);  vis[0][mm.x][mm.y]=1;    q[1].push(gg);  vis[1][gg.x][gg.y]=1;    step=0;    while ((!q[0].empty()) || (!q[1].empty()))    {        step++;        if(bfs(0)) return step;        if(bfs(0)) return step;        if(bfs(0)) return step;        if(bfs(1)) return step;    }    return -1;}int main(){    int T;    scanf("%d",&T);    while(T--)    {        scanf("%d%d",&n,&m);        int znum=0;        for(int i=0;i<n;++i) scanf("%s",map[i]);        for(int i=0;i<n;++i)        {            for(int j=0;j<m;++j)            {                if(map[i][j]=='M')  {mm.x=i;mm.y=j;}                if(map[i][j]=='G')  {gg.x=i;gg.y=j;}                if(map[i][j]=='Z')  {z[znum].x=i; z[znum++].y=j;}            }        }        printf("%d\n",work());    }    return 0;}