【DFS】codeforces B. Sagheer, the Hausmeister

时间:2023-03-09 19:23:34
【DFS】codeforces B. Sagheer, the Hausmeister

http://codeforces.com/contest/812/problem/B

【题意】

有一个n*m的棋盘,每个小格子有0或1两种状态,现在要把所有的1都变成0,问最少的步数是多少?初始位置在左下角,只有把下面一层的1都变成0后才可以到上一层,只有在每层的最右边和最左边可以向上走(up),否则只能左右移动(left or right)。只要经过1,就可以把1变成0,只要把最后一个1,就可以立即停止操作。

【Accepted】

 #include <iostream>
#include <stdio.h>
#include <cmath>
#include <vector>
#include <algorithm>
#include <set>
#include <map>
#include <queue>
#include <deque>
#include <stack>
#include <string>
#include <bitset>
#include <ctime>
#include<algorithm>
#include<cstring>
using namespace std;
int n,m;
const int maxn=1e2+;
char s[maxn];
int a[][maxn];
int sum[];
int ans;
int fir[];
int sec[];
const int inf=0x3f3f3f3f;
int index;
void dfs(int cur,int flag,int cnt)
{
if(cur==index)
{
if(flag)
{
int t=cnt+sec[index]-;
ans=min(ans,t);
return;
}
else
{
int t=cnt+m+-fir[index];
ans=min(ans,t);
return;
}
}
if(flag)
{
if(sum[cur])
{
dfs(cur-,,cnt+m+);
dfs(cur-,,cnt+*(sec[cur]-)+);
}
else
{
dfs(cur-,,cnt+);
}
}
else
{
if(sum[cur])
{
dfs(cur-,,cnt+m+);
dfs(cur-,,cnt+*(m+-fir[cur])+);
}
else
{
dfs(cur-,,cnt+);
}
} }
int main()
{
while(~scanf("%d%d",&n,&m))
{
memset(sum,,sizeof(sum));
memset(fir,-,sizeof(fir));
memset(sec,,sizeof(sec));
ans=inf;
for(int i=;i<=n;i++)
{
scanf("%s",s+);
for(int k=;k<=m+;k++)
{
a[i][k]=s[k]-'';
sum[i]+=a[i][k];
//每层最右的1的位置
if(a[i][k])
{
sec[i]=k;
}
//每层最左的1的位置
if(a[i][k]&&fir[i]==-)
{
fir[i]=k;
}
}
}
int cou=;
//index表示走到第几层为止,因为上面的都是0
index=;
for(int i=;i<=n;i++)
{
cou+=sum[i];
if(cou!=)
{
index=i;
break;
}
}
//特判,如果数据都是0
if(index==)
{
printf("0\n");
continue;
}
//分别表示第几层,当前层的初始位置在最左边还是最右边,步数
dfs(n,,);
cout<<ans<<endl;
}
return ;
}

DFS:2^15

时间复杂度是2^15

没有考虑的都是0的corner case,疯狂wa