参考某大佬的思路:dp[I][0/1]表示已经灭掉第I层的灯,并且在第I层的左/右端
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 20;
const int maxm = 110;
int L[maxm],R[maxm];
int dp[maxn][2];
int main()
{
int n,m;
char s[maxm];
// freopen("in.txt","r",stdin);
while(cin>>n>>m)
{
int mx=1<<30;
for(int i=1;i<=n;i++)
{
L[i]=1e5;R[i]=-1;
cin>>s;
for(int j=0;j<m+2;j++)
{
if(s[j]=='1')
{
L[i]=min(L[i],j);
R[i]=max(R[i],j);
mx=min(mx,i);
}
}
if(L[i]==1e5)
L[i]=0,R[i]=m+1;
}
int ans=0;
for(int i=n;i>=mx;i--)
{
if(L[i]==0)//i层为空
{
if(i==n)
{
dp[i][0]=0,dp[i][1]=m+1;
}
else
{
dp[i][0]=dp[i+1][0]+1;
dp[i][1]=dp[i+1][1]+1;
}
continue;
}
if(i==mx)
{
ans=min(dp[i+1][0]+1+R[i],dp[i+1][1]+1+(m+1)-L[i]);
continue;
}
if(i==n)
{
dp[i][0]=R[i]*2;
dp[i][1]=m+1;
continue;
}
dp[i][0]=min(dp[i+1][0]+2*R[i]+1,dp[i+1][1]+m+2);//灭掉 当前层灯
dp[i][1]=min(dp[i+1][0]+m+2,dp[i+1][1]+2*(m+1-L[i])+1);
}
if(mx==n)
{
ans=R[n];
}
cout<<ans<<endl;
}
}