题意:
有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;
}