CF - 812B. Sagheer, the Hausmeister - 暴力+dp

1.题目描述:

B. Sagheer, the Hausmeister
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

Some people leave the lights at their workplaces on when they leave that is a waste of resources. As a hausmeister of DHBW, Sagheer waits till all students and professors leave the university building, then goes and turns all the lights off.

The building consists of n floors with stairs at the left and the right sides. Each floor has m rooms on the same line with a corridor that connects the left and right stairs passing by all the rooms. In other words, the building can be represented as a rectangle with n rows and m + 2 columns, where the first and the last columns represent the stairs, and the m columns in the middle represent rooms.

Sagheer is standing at the ground floor at the left stairs. He wants to turn all the lights off in such a way that he will not go upstairs until all lights in the floor he is standing at are off. Of course, Sagheer must visit a room to turn the light there off. It takes one minute for Sagheer to go to the next floor using stairs or to move from the current room/stairs to a neighboring room/stairs on the same floor. It takes no time for him to switch the light off in the room he is currently standing in. Help Sagheer find the minimum total time to turn off all the lights.

Note that Sagheer does not have to go back to his starting position, and he does not have to visit rooms where the light is already switched off.

Input

The first line contains two integers n and m (1 ≤ n ≤ 15 and 1 ≤ m ≤ 100) — the number of floors and the number of rooms in each floor, respectively.

The next n lines contains the building description. Each line contains a binary string of length m + 2 representing a floor (the left stairs, then m rooms, then the right stairs) where 0 indicates that the light is off and 1 indicates that the light is on. The floors are listed from top to bottom, so that the last line represents the ground floor.

The first and last characters of each string represent the left and the right stairs, respectively, so they are always 0.

Output

Print a single integer — the minimum total time needed to turn off all the lights.

Examples
input
2 2
0010
0100
output
5
input
3 4
001000
000010
000010
output
12
input
4 3
01110
01110
01110
01110
output
18
Note

In the first example, Sagheer will go to room 1 in the ground floor, then he will go to room 2 in the second floor using the left or right stairs.

In the second example, he will go to the fourth room in the ground floor, use right stairs, go to the fourth room in the second floor, use right stairs again, then go to the second room in the last floor.

In the third example, he will walk through the whole corridor alternating between the left and right stairs at each floor.


2.题意概述:

给你一栋Nx(M+2)楼的灯的情况,其中第,0列和第m+1列为楼梯,某个房间如果有灯亮着,则为1,否则为0,某人在楼的左下角,即坐标为(0,n-1)处,它想把整栋楼的灯都关了,但是他上楼只能通过楼梯,忽略关灯时间,且每移动一个单位需要1s,问把整栋楼的灯全部熄灭的最小时间(不需要回到起点)。

3.解题思路:

考虑动态规划,dp[i][0]表示把前i层的灯完全熄灭并回到第i层的左侧楼道,dp[i][1]表示把前i层的灯完全关闭并回到第i层右侧楼道,那么很容易写出转移方程:

(其中i从n-1到0,因为读入的地图底层是从n-1开始的QAQ)

其中c[i][0]表示从i层左侧出发关掉第i层灯需要的步数,c[i][1]表示从i层右侧出发关掉第i层灯需要的步数。这个很容易通过暴力算出来。

下面是需要注意的一些地方

  1. 但是这样还不够,因为可能到达某一层(非顶层)就已经没灯了,这时候就不需要关,所以还得记录一下最高需要关到什么位置。
  2. 而且最后一层没必要回到左侧(或者右侧),只要关完灯就可以了。
  3. 还有个坑就是只有一层时候,由于主人公在左侧,这个时候只能从左侧出发去关灯。

这道题细节挺多的,如果dp不处理好,容易卡在细节上。

4.AC代码:

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define maxn 100010
#define lson root << 1
#define rson root << 1 | 1
#define lent (t[root].r - t[root].l + 1)
#define lenl (t[lson].r - t[lson].l + 1)
#define lenr (t[rson].r - t[rson].l + 1)
#define N 1111
#define eps 1e-6
#define pi acos(-1.0)
#define e exp(1.0)
using namespace std;
const int mod = 1e9 + 7;
typedef long long ll;
typedef unsigned long long ull;
char mp[16][103];
int dp[16][2], c[16][2];	// dp[i][0]关掉前i层回到左边,dp[i][1]关掉前i层回到右边,c[i][0]左边出发关掉第i层并回到左边,c[i][1]右边出发关掉第i层并回到右边
int main()
{
#ifndef ONLINE_JUDGE
	freopen("in.txt", "r", stdin);
	freopen("out.txt", "w", stdout);
	long _begin_time = clock();
#endif
	int n, m;
	scanf("%d%d", &n, &m);
	int last = n - 1;
	for (int i = 0; i < n; i++)
	{
		scanf("%s", mp[i]);
		int left = 0, right = m + 1;
		for (int j = 0; j < m + 2; j++)
			if (mp[i][j] == '1')
				left = j;
		for (int j = m + 1; j > 0; j--)
			if (mp[i][j] == '1')
				right = j;
		c[i][0] = left;
		c[i][1] = m + 1 - right;
		if (c[i][0])
			last = min(last, i);
	}
	dp[n - 1][0] = 2 * c[n - 1][0];
	dp[n - 1][1] = m + 1;
	for (int i = n - 2; i >= 0; i--)
	{
		dp[i][0] = min(dp[i + 1][0] + 2 * c[i][0], dp[i + 1][1] + m + 1) + 1;
		dp[i][1] = min(dp[i + 1][0] + m + 1, dp[i + 1][1] + 2 * c[i][1]) + 1;
	}
	int ans = min(dp[last + 1][0] + c[last][0], dp[last + 1][1] + c[last][1]) + 1;
	if (last == n - 1)
		ans = c[last][0];
	printf("%d\n", ans);
#ifndef ONLINE_JUDGE
	long _end_time = clock();
	printf("time = %ld ms.", _end_time - _begin_time);
#endif
	return 0;
}

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值