zoukankan      html  css  js  c++  java
  • 2018多校第九场 HDU 6416 (DP+前缀和优化)

    转自:https://blog.csdn.net/CatDsy/article/details/81876341

    #include <bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define ull unsigned long long
    #define mst(a,b) memset((a),(b),sizeof(a))
    #define pi acos(-1)
    #define pii pair<int,int>
    const int INF = 0x3f3f3f3f;
    const double eps = 1e-6;
    const int MAXN = 2e3 + 10;
    const int MAXM = 2e6 + 10;
    const ll mod = 998244353;
    
    char s[MAXN][MAXN];
    ll tot[MAXN][MAXN], same[MAXN][MAXN];
    ll pre_tot[MAXN][MAXN], pre_same[MAXN][MAXN];
    
    int main() {
    #ifdef local
        freopen("data.txt", "r", stdin);
    //    freopen("data.txt", "w", stdout);
    #endif
        int t;
        scanf("%d",&t);
        while(t--) {
            int n,m,k;
            scanf("%d%d%d",&n,&m,&k);
            for(int i = 1; i <= n; i++)
                scanf("%s",s[i] + 1);
            for(int i = 1; i <= n; i++)
                pre_tot[i][0] = pre_same[i][0] = 0;
            for(int i = 1; i <= m; i++) {
                tot[1][i] = 1;
                pre_tot[1][i] = i;
                if(i == 1 || s[1][i] != s[1][i - 1]) same[1][i] = 0;
                else same[1][i] = 1;
                pre_same[1][i] = pre_same[1][i - 1] + same[1][i];
            }
            for(int i = 2; i <= n; i++) {
                for(int j = 1; j <= m; j++) {
                    int l = max(j - k, 1), r = min(j + k, m);
                    tot[i][j] = (pre_tot[i - 1][r] - pre_tot[i - 1][l - 1] + mod) % mod;
                    l = max(j - k + 1, 1), r = min(j + k, m);
                    tot[i][j] = (tot[i][j] - (pre_same[i - 1][r] - pre_same[i - 1][l - 1] + mod) % mod + mod) % mod;
                    pre_tot[i][j] = (pre_tot[i][j - 1] + tot[i][j]) % mod;
                    if(j == 1 || s[i][j] != s[i][j - 1]) same[i][j] = 0;
                    else {
                        l = max(j - k, 1), r = min(j + k - 1, m);
                        same[i][j] = (pre_tot[i - 1][r] - pre_tot[i - 1][l - 1] + mod) % mod;
                        l = max(j - k + 1, 1), r = min(j + k - 1, m);
                        same[i][j] = (same[i][j] - (pre_same[i - 1][r] - pre_same[i - 1][l - 1] + mod) % mod + mod) % mod;
                    }
                    pre_same[i][j] = (pre_same[i][j - 1] + same[i][j]) % mod;
                }
            }
            ll ans = 0;
            for(int i = 1; i <= m; i++)
                ans = (ans + tot[n][i] - same[n][i] + mod) % mod;
            printf("%lld
    ",ans);
        }
        return 0;
    }

    题目描述:

    给定一个NMN∗M的01矩阵

    K-seam是满足以下条件的整数序列a:

    • |a|=n,ai[1,m]|a|=n,ai∈[1,m]
    • |aiai+1|K,i[1,n)|ai−ai+1|≤K,i∈[1,n)

    对于第ii行,删除第aiai个数,会得到一个N(M1)N∗(M−1)的矩阵

    不同的整数序列可能会得到相同的矩阵

    问:可以得到多少种不同的矩阵


    题解:

    如果无视different的条件 
    定义状态:dp[i][j]dp[i][j]——删除第 ii 行第 jj 个数可以得到的矩阵总数 
    可推得转移方程如下:

     
    dp[i][j]=x=jkj+kdp[i1][x]dp[i][j]=∑x=j−kj+kdp[i−1][x]

     

    在此基础上,加上different的条件 
    定义状态:

    • tot[i][j]tot[i][j]——删除第 ii 行第 jj 个数可以得到的不同的矩阵总数
    • same[i][j]same[i][j]——删除第 ii 行第 jj 个数和删除第 ii 行第 j1j−1 个数后得到的相同方案数

    那么,tot[i][j]tot[i][j]的状态转移方程为: 

     
    tot[i][j]=x=jkj+ktot[i1][x]x=jk+1j+ksame[i1][x]tot[i][j]=∑x=j−kj+ktot[i−1][x]−∑x=j−k+1j+ksame[i−1][x]


    如果 Matrix[i][j]Matrix[i][j1]Matrix[i][j]≠Matrix[i][j−1] 那么,same[i][j]=0same[i][j]=0 
    否则,对于第 jj 个和第 j1j−1 个的转移区间分别为[jk,j+k][j−k,j+k][j1k,j1+k][j−1−k,j−1+k],那么它们的交叉区间为[jk,j1+k][j−k,j−1+k],即:从该区间内转移得到的方案数会重复计算一次。得到 same[i][j]same[i][j] 的转移方程为: 

     
    same[i][j]=x=jkj+k1tot[i1][x]x=jk+1j+k1same[i1][x]same[i][j]=∑x=j−kj+k−1tot[i−1][x]−∑x=j−k+1j+k−1same[i−1][x]

     

    时间复杂度为O(nm2)O(n∗m2),对于做前缀和优化,时间复杂度降为O(nm)O(n∗m)

    最后,对于第n行计算总的不同的方案数,即ans=totsame

  • 相关阅读:
    LeetCode 81 Search in Rotated Sorted Array II(循环有序数组中的查找问题)
    LeetCode 80 Remove Duplicates from Sorted Array II(移除数组中出现两次以上的元素)
    LeetCode 79 Word Search(单词查找)
    LeetCode 78 Subsets (所有子集)
    LeetCode 77 Combinations(排列组合)
    LeetCode 50 Pow(x, n) (实现幂运算)
    LeetCode 49 Group Anagrams(字符串分组)
    LeetCode 48 Rotate Image(2D图像旋转问题)
    LeetCode 47 Permutations II(全排列)
    LeetCode 46 Permutations(全排列问题)
  • 原文地址:https://www.cnblogs.com/scaulok/p/9580628.html
Copyright © 2011-2022 走看看