#417 Div2 B

#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;
}
原文地址:https://www.cnblogs.com/ftae/p/6931507.html