天天看点

codeforces 812 B Sagheer, the Hausmeister(枚举)

题意:

有n层楼,小明需要从一层楼的左边开始去关n层楼种还未关灯的房间的灯,其中一层中最左边和最右边都是楼梯,问小明关完所有灯的时间,不需要计算返回的时间

解题思路:

小明到达一层楼只有从左边和右边楼梯上来两种情况,离开也一样,所以一旦确定当前这一层楼小明是从哪边上来,要从哪边离开,那么这层楼要怎么走就已经确定下来了。这里n只有15,所以我们只需要2^x(有灯亮的最顶层)去枚举每一层楼的情况,最后算下答案,所有情况的答案取最小值就是最后的答案了。

代码:

#include <bits/stdc++.h>

using namespace std;
int ord[22];
int a[23][105];
int l[105], r[105];
int ans, n, m;
void dfs(int x)
{
    int i, j;
    if(x>n)
    {
        int sum=0;
//        for(i=1; i<=n; i++)printf("%d", ord[i]);printf("\n");
        for(i=1; i<=n; i++)
        {
            if(i==n)
            {
                if(ord[i]==0)
                {
                    sum+=r[i]==0?-1:r[i];
                }
                else sum+=(l[i]==0)?-1:(m-1-l[i]);
                break;
            }
            if(ord[i]==0)
            {
                if(ord[i+1]==0)
                {
                    sum+=2*r[i];
                }
                else
                {
                    sum+=m-1;
                }
            }
            else
            {
                if(ord[i+1]==1)
                {
                    sum+=(l[i]==0)?0:(m-1-l[i])*2;
                }
                else
                {
                    sum+=m-1;
                }
            }

            sum++;
//            cout<<sum<<endl;
        }

        ans=sum<ans?sum:ans;
        return;
    }
    ord[x]=1;
    dfs(x+1);
    ord[x]=0;
    dfs(x+1);
    return;
}
int main()
{
    int i, j;

    cin>>n>>m;
    ans=n*m*4;
    m+=2;
    ord[1]=0;
    int s=n+1, num;
    for(i=n; i>=1; i--)
    {
        num=0;
        for(j=0; j<m; j++)
        {
            scanf("%1d", &a[i][j]);
            if(a[i][j])
            {
                r[i]=j;
                num++;
                if(!l[i])l[i]=j;
            }

        }
        if(num==0 && s==i+1)
        {
            s=i;
        }
    }
    n=s-1;
    dfs(2);
    printf("%d\n", ans);
    return 0;
}