#417 Div2 B
题意
给定一个01矩阵表示一幢楼,左右两侧是楼梯,中间是房间,1代表那个房间开灯,0代表关灯,现在某人从1层左端楼梯开始关掉所有灯,当移动某一层时,必须关掉当前层所有灯才能移动到下一层,每次在楼层间或房间间移动耗费时间为1,关灯不需要时间,问最短时间花费。
分析
移动某一层时,必须关掉当前层所有灯才能移动到下一层,所以移动到下一层的位置一定是最左端或最右端有灯的房间(如果当前层没有灯的话继续向下移动)。
DP,当然记忆化无脑搜一下就好。
code
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 1e5 + 10;
int a[20][110], dp[20][110];
int L[20], R[20];
int n, m;
void dfs(int x, int y, int res) {
if(res > dp[x][y]) {
return;
}
dp[x][y] = res;
int x_ = x + 1;
while(x_ <= n && L[x_] == -1) {
x_++;
}
if(x_ == n + 1) return;
if(x == 0) {
if(x_ == 1) dfs(x_, R[x_], res + R[x_] - 1);
else {
dfs(x_, R[x_], res + x_ - x - 1 + R[x_] - 1);
dfs(x_, L[x_], res + x_ - x - 1 + m + 1 + m + 2 - L[x_]);
}
} else {
dfs(x_, L[x_], res + m + 2 - L[x_] + m + 2 - y + x_ - x);
dfs(x_, R[x_], res + R[x_] - 1 + y - 1 + x_ - x);
}
}
int main() {
cin >> n >> m;
memset(L, -1, sizeof L);
for(int i = 0; i < 20; i++) {
for(int j = 0; j < 110; j++) {
dp[i][j] = 1e9;
}
}
for(int i = n; i >= 1; i--) {
string s;
cin >> s;
for(int j = 1; j <= m + 2; j++) {
a[i][j] = s[j - 1] - '0';
if(a[i][j] && L[i] == -1) L[i] = j;
if(a[i][j]) R[i] = j;
}
}
dfs(0, 0, 0);
int flg = 0;
for(int i = n; i >= 0; i--) {
if(L[i] != -1) {
cout << min(dp[i][L[i]], dp[i][R[i]]) << endl;
flg = 1;
break;
}
}
if(!flg) cout << 0 << endl;
return 0;
}