zoukankan      html  css  js  c++  java
  • 1126: [POI2008]Uci

    1126: [POI2008]Uci

    https://lydsy.com/JudgeOnline/problem.php?id=1126

    分析:

      dp。状态很妙,就是有点难写。

      能走的是一个矩形。首先考虑从x,y只能往左拐,到n,1的方案数。矩形是增加的。然后f[u][l][d][r][0/1/2/3]表示上边界u,左边界l,下边界d,右边界r的矩形,在左上角/右下角/左下角/左上角的方案数。

      然后考虑这个从这个点可以沿着原来的方向走一步。或者拐弯(拐弯后直接到下一个角上,比如在右下角,拐弯后到右上角)。

      初始值设为可以到x,y的,所有的点,尽管这些状态是不存在的。

      空间开不下,把第一维滚动掉。

      (开始想的的“推”的dp,这样的话初始值就比较方便了,但是就无法滚动第一维了)

    代码:

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<iostream>
     5 #include<cmath>
     6 #include<cctype>
     7 #include<set>
     8 #include<queue>
     9 #include<vector>
    10 #include<map>
    11 using namespace std;
    12 typedef long long LL;
    13 
    14 inline int read() {
    15     int y=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
    16     for(;isdigit(ch);ch=getchar())y=y*10+ch-'0';return y*f;
    17 }
    18 
    19 const int N = 105;
    20 
    21 int sr[N][N], sc[N][N], f[2][N][N][N][4];
    22 char s[N];
    23 int mod;
    24 
    25 inline void add(int &x,int y) {
    26     x += y; if (x >= mod) x -= mod;
    27 }
    28 
    29 int main() {
    30     int n = read(), m = read();mod = read();int x = read(), y = read();
    31     for (int i = 1; i <= n; ++i) {
    32         scanf("%s", s + 1);
    33         for (int j = 1; j <= m; ++j) {
    34             sr[i][j] = sr[i][j - 1] + (s[j] == '+');
    35             sc[i][j] = sc[i - 1][j] + (s[j] == '+');
    36         } 
    37     }
    38     int ans = 0;
    39     f[1][x][y][x][0] = 1;
    40     f[0][x][y][x - 1][1] = 1;
    41     f[0][x][y - 1][x][2] = 1;
    42     f[0][x + 1][y][x][3] = 1;
    43 
    44     for (int u = y, now = 0; u >= 1; --u, now ^= 1) {
    45         if (u != y) memset(f[now], 0, sizeof(f[now]));
    46         for (int l = x; l >= 1; --l) 
    47             for (int d = y; d <= n; ++d) 
    48                 for (int r = x; r <= m; ++r) {
    49                     if (sc[d][r] - sc[u - 1][r] == d - u + 1) {
    50                         f[now][l][d][r][0] = f[now][l][d][r - 1][1];
    51                         if (u < d) add(f[now][l][d][r][0], f[!now][l][d][r][0]);
    52                     }
    53                     if (sr[d][r] - sr[d][l - 1] == r - l + 1) {
    54                         f[now][l][d][r][1] = f[now][l][d - 1][r][2];
    55                         if (l < r) add(f[now][l][d][r][1], f[now][l][d][r - 1][1]);
    56                     }
    57                     if (sc[d][l] - sc[u - 1][l] == d - u + 1) {
    58                         f[now][l][d][r][2] = f[now][l + 1][d][r][3];
    59                         if (u < d) add(f[now][l][d][r][2], f[now][l][d - 1][r][2]);
    60                     }
    61                     if (sr[u][r] - sr[u][l - 1] == r - l + 1) {
    62                         f[now][l][d][r][3] = f[!now][l][d][r][0];
    63                         if (l < r) add(f[now][l][d][r][3], f[now][l + 1][d][r][3]);
    64                     }
    65                     if (u == y && d == y && l == x && r == x) {
    66                         f[1][x][y][x][0] = 0;
    67                         f[0][x][y][x - 1][1] = 0;
    68                         f[0][x][y - 1][x][2] = 0;
    69                         f[0][x + 1][y][x][3] = 0;
    70                     }
    71                     if (l == 1 && d == n) add(ans, f[now][l][d][r][2]);
    72                 }
    73     }
    74     cout << ans;
    75     return 0;
    76 }
  • 相关阅读:
    jquery使用技巧
    依赖倒置原则
    java程序设计单一原则
    java中的 break continue return作用详解
    织梦标签问题集锦--持续补充
    织梦文章列表过长自动省略号隐藏
    织梦网站地图如何修改生成路径?
    织梦发布的文章如何批量替换文章"来源"和"作者"?
    织梦仿站列表页pagelist分页显示竖排,如何修改成横排?
    织梦仿站自定义表单如何在后台显示时间?
  • 原文地址:https://www.cnblogs.com/mjtcn/p/10039181.html
Copyright © 2011-2022 走看看