题意:n<15,m<=100的矩阵 1为亮,0为灭 每层第一个和最后一个位置为楼梯,每层必须灭完才能到上一层,问全部灯灭完 最小时间?
到上一层只能从左端或者右端走 设dp[i][0/1] : 灭了前i层的灯 &&当前在第i层左/右端时的最小时间
dp[i][0]=min(dp[i+1][0]+1+(r[i]-1)*2,dp[i+1][1]+1+m-1)
第i层没灯时 dp[i][0]=dp[i+1][0] 坑点:只有一层,第一层为空...
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll,ll> ii;
const int inf=2e8;
const double eps=1e-11;
const int N=2e3+20;
int n,m,l[N],r[N];
int f[N][2];//f[i][0/1] dp[i][0] 关了i-1层&&当前在第i层左端点
char s[N];
int main()
{
while(cin>>n>>m)
{
m+=2;
int mx=n+1;
memset(l,0,sizeof(l));
memset(r,0,sizeof(r));
for(int i=1;i<=n;i++)
{
l[i]=1e5,r[i]=0;
scanf("%s",s+1);
for(int j=1;j<=m;j++)
{
if(s[j]=='1')
{
l[i]=min(l[i],j);
r[i]=max(r[i],j);
mx=min(i,mx);//最后一层
}
}
if(l[i]==1e5)
l[i]=1,r[i]=m;
}
memset(f,0,sizeof(f));
int ans=0;
for(int i=n;i>=mx;i--)
{
if(r[i]==m)
{
if(i==n)//第1层为空
f[i][0]=0,f[i][1]=m-1;
else
{
f[i][0]=f[i+1][0]+1;
f[i][1]=f[i+1][1]+1;
}
continue;
}
if(i==mx)
{
ans=min(f[i+1][0]+1+r[i]-1,f[i+1][1]+1+(m-l[i]));
break;
}
if(i==n)
{
f[i][0]=2*(r[i]-1);
f[i][1]=m-1;
continue;
}
f[i][0]=min(f[i+1][0]+(r[i]-1)*2+1,f[i+1][1]+m-1+1);
f[i][1]=min(f[i+1][0]+m-1+1,f[i+1][1]+(m-l[i])*2+1);
}
if(mx==n)
ans=r[mx]-1;
cout<<ans<<endl;
}
return 0;
}