Codeforecs 812B Sagheer, the Hausmeister DP

点击打开链接

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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值