Bronze 确实都是简单题,我这种撒币都能做得来

# Method

考虑一个 dp[x][y][转弯次数][方向] 代表在这些条件下的合法路径数

  • 转弯次数:路径上共有多少转弯处 (00 ~ kk,在此题中最高为 33)
  • 方向:上一个位置向当前位置前进的方向 (0/10/1)
    • 00 为右,11 为下
  • 当上一个状态的方向与当前状态的方向不同时将转弯次数 +1+1
  • 当前位置有障碍物时设为 00

同时这种方法需要进一步优化

将每一个在顶边或左边的块设为 1100 次转弯的路径,00 条其他转弯次数的路径

当顶边或左边中某一块为障碍物,将其右侧(顶边)或底部(左边)的块设为无路径可达


# Code

int T, n, k, ans;
int dp[100][100][4][2];
int main() {
    read(T);
    while(T--) {
        ans = 0;
        read(n, k);
        for(int i = 1; i <= n; ++i) dp[1][i][0][0] = 1;
        for(int i = 1; i <= n; ++i) dp[i][1][0][1] = 1;
        for(int i = 1; i <= n; ++i) {
            for(int j = 1; j <= n; ++j) {
                char c = getchar();
                if(i == 1 || j == 1) {
                    if(c == 'H')
                        if(i == 1)
                            for(int l = j; l <= n; ++l) dp[i][l][0][0] = dp[i][l][0][1] = 0;
                        else if(j = 1) 
                            for(int l = i; l <= n; ++l) dp[l][j][0][0] = dp[l][j][0][1] = 0;
                    continue;
                }
                for(int l = 0; l <= k; ++l)
                    if(!l) {
                        dp[i][j][l][0] = dp[i][j - 1][l][0];
                        dp[i][j][l][1] = dp[i - 1][j][l][1];
                    } else if(c == '.') {
                        dp[i][j][l][0] =    dp[i][j - 1][l - 1][1] + 
                                            dp[i][j - 1][l][0];
                        dp[i][j][l][1] =    dp[i - 1][j][l - 1][0] + 
                                            dp[i - 1][j][l][1];
                    } else if(c == 'H') dp[i][j][l][0] = dp[i][j][l][1] = 0;
            }
            getchar();
        }
        for(int i = 1; i <= k; ++i) ans += dp[n][n][i][0] + dp[n][n][i][1];
        writeln(ans);
    }
}
更新于 阅读次数

请我喝[茶]~( ̄▽ ̄)~*

saltcute 微信支付

微信支付

saltcute 支付宝

支付宝

saltcute 贝宝

贝宝