Codeforces Round #417 (Div. 2) B. Sagheer, the Hausmeister dfs深度优先搜索

一道深度优先搜索题,其实dp应该也可以 只是目前对dp还不是很熟练

上代码看注释吧


 #include<algorithm>
 #include<iostream>
 #include<cstdlib>
 #include<cstring>
 #include<cstdio>
 #include<string>
 #include<stack>
 #include<queue>
 #include<cmath>
 #include<stack>
 #include<list>
 #include<map>
 #include<set>
 typedef long long ll;
 using namespace std;
 int book[20]; //记录第i层 开着灯的房间的个数
 char a[20][110]; //输入的地图
 int b[20][3]; // 记录第i层最左边和最右边的开灯房间的位置 b[i][0]代表最左 b[i][1]代表最右边
 int cnt=0;//记录开灯房间的总个数
 int m,n;
 int maxn=0xffffff; // 要输出的答案 不断更新maxn 使其最小
 void dfs(int t,int p,int ge,int d) //t代表层数,p是pace,代表时间 ge代表当前已经关掉了ge个灯,d代表方向,d==0代表从左楼梯上,==1代表从右楼梯上
 {
     if(ge==cnt)
     {
         maxn=min(maxn,p);
         return ;
     }
     if(d==0) //从左楼梯上来的,此时人位于最左边
     {
         if(b[t][1]!=-1&&b[t][0]!=-1) //如果这一层存在开着的灯
         {

              if(ge+book[t]==cnt) //关完这一层的灯就全部关掉了
             {
                  maxn=min(maxn,p+b[t][1]);
                  return ;
             }
             else
             {
                 dfs(t-1,p+2*b[t][1]+1,ge+book[t],0); //仍然从左楼梯上楼,要走来回 所以是2倍 上楼花一分钟
                 dfs(t-1,p+m+1+1,ge+book[t],1); //换到右楼梯上楼 相当于直接走到右边 上楼花一分钟
             }
         }
         else //如果这一层不存在开着的灯
         {
             dfs(t-1,p+1,ge,0);  //直接进入下一层
             dfs(t-1,p+m+1+1,ge,1); //走到右楼梯 再进入下一层
         }
     }
     else if(d==1) //从右楼梯上来的,此时人位于最右边
     {
          if(b[t][1]!=-1&&b[t][0]!=-1)
          {

             if(ge+book[t]==cnt)//关完这一层的灯就全部关掉了
             {
                  maxn=min(maxn,p+m+1-b[t][0]);
                  return ;
             }
             else
             {
               dfs(t-1,p+2*(m+1-b[t][0])+1,ge+book[t],1);
               dfs(t-1,p+m+1+1,ge+book[t],0);
             }
          }
          else
          {
              dfs(t-1,p+1,ge,1);
              dfs(t-1,p+m+1+1,ge,0);
          }
     }
     return;
}
int main()
{
        int i,j,k;
        scanf("%d%d",&n,&m);
        maxn=0xffffff;
        cnt=0;
        memset(b,-1,sizeof b); //初始化为-1
        memset(book,0,sizeof book);
        getchar();
        for(i=1;i<=n;i++)
        {
            int flag=0;
            for(j=0;j<=m+1;j++)
            {
                 scanf("%c",&a[i][j]);
                 if(a[i][j]=='1')
                 {
                     cnt++;
                     book[i]++;
                     if(flag==0)
                     {
                        flag=1;
                        b[i][0]=j;
                     }
                 }
            }
            getchar();
            for(j=m+1;j>=0;j--)
            {
                if(a[i][j]=='1')
                {
                    b[i][1]=j;
                    break;
                }
            }
        }
        dfs(n,0,0,0);
        printf("%d\n",maxn);
    return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值