zoukankan      html  css  js  c++  java
  • Codeforces Round #642 (Div. 3) E、F

    K-periodic Garland

    题目链接:https://codeforces.com/contest/1353

    题目大意:

    给你一个长度为 n 的 01 字符串和一个整数 k,每次操作你可以选择一个字符并改变其状态,要使字符串中相邻 1 的距离为 k,问最少需要操作几次。

    想法:

    我们设 dp[i][0/1] 

    dp[i][0] 代表第 i 项是 0 的合法序列的最小修改次数

    dp[i][1] 代表第 i 项是 1 的合法序列的最小修改次数

    明显dp[i][0] 转移的方程: 要么前面一项是 1 合法 或者 前面一项是 0 合法,min(dp[i-1][0],dp[i-1][1])

    明显dp[i][1] 转移的方程: 要么前面 i-1 项全部是0,或者 i - k 项是合法的结尾是 1 的序列并且 i - k + 1 ~ i - 1 都是 0 ,min(sum[i-1],dp[p][1]+sum[i-1]-sum[p])

    采用前缀和预处理一下 1 的个数。

    #pragma GCC optimize(2)
    #pragma GCC optimize(3)
    
    #include <algorithm>
    #include <string>
    #include <cstring>
    #include <vector>
    #include <map>
    #include <stack>
    #include <set>
    #include <queue>
    #include <cmath>
    #include <cstdio>
    #include <iomanip>
    #include <ctime>
    #include <bitset>
    #include <cmath>
    #include <sstream>
    #include <iostream>
    
    #define ll long long
    #define ls nod<<1
    #define rs (nod<<1)+1
    #define pii pair<int,int>
    #define mp make_pair
    #define pb push_back
    #define INF 0x3f3f3f3f3f3f3f3f
    #define max(a, b) (a>b?a:b)
    #define min(a, b) (a<b?a:b)
    
    
    const double eps = 1e-10;
    const int maxn = 1e6 + 10;
    const int MOD = 998244353;
    
    int sgn(double a) { return a < -eps ? -1 : a < eps ? 0 : 1; }
    
    using namespace std;
    
    char s[maxn];
    int dp[maxn][2],sum[maxn];
    
    
    int main() {
        int t;
        scanf("%d",&t);
        while (t--) {
            int n,k;
            scanf("%d%d",&n,&k);
            scanf("%s",s+1);
            dp[0][0] = dp[0][1] = 0;
            for (int i = 1;i <= n;i++) {
                sum[i] = sum[i - 1] + (s[i] == '1');
                dp[i][0] = dp[i][1] = 0;
            }
            for (int i = 1;i <= n;i++) {
                int p = max(0,i-k);
                dp[i][0] = min(dp[i-1][1],dp[i-1][0]) + (s[i] == '1');
                dp[i][1] = min(sum[i-1],dp[p][1]+sum[i-1]-sum[p]) + (s[i] == '0');
            }
            printf("%d
    ",min(dp[n][0],dp[n][1]));
        }
        return 0;
    }

    Decreasing Heights

    题目链接:https://codeforces.com/contest/1353

    题目大意:

    想法:

    考虑如果不做操作,就是一道很经典的dp,所以现在需要确定的是,操作结束之后的矩阵。

    首先一定会有一个格子的高度保持不变

    由起点的高度可以推得所有格子的高度

    所以我们枚举高度不变的格子,依据他计算出起点高度,之后枚举起点高度即可

    设 f[i][j] 代表从 f[0][0] 到 (i,j) 所需要的修改的最小次数

    转移方程的化和数塔问题是一样的  if (j >= 1)   f[i][j] = min(f[i][j],f[i][j-1]);       f (i >= 1)   f[i][j] = min(f[i][j],f[i-1][j]);

    枚举起点的复杂度是O(n^2),dp 的复杂度是 O(n^2), 总的复杂是 O(n^4)

    #pragma GCC optimize(2)
    #pragma GCC optimize(3)
    
    #include <algorithm>
    #include <string>
    #include <cstring>
    #include <vector>
    #include <map>
    #include <stack>
    #include <set>
    #include <queue>
    #include <cmath>
    #include <cstdio>
    #include <iomanip>
    #include <ctime>
    #include <bitset>
    #include <cmath>
    #include <sstream>
    #include <iostream>
    
    #define ll long long
    #define ls nod<<1
    #define rs (nod<<1)+1
    #define pii pair<int,int>
    #define mp make_pair
    #define pb push_back
    #define INF 0x3f3f3f3f3f3f3f3f
    #define max(a, b) (a>b?a:b)
    #define min(a, b) (a<b?a:b)
    
    
    const double eps = 1e-10;
    const int maxn = 100 + 10;
    const int MOD = 998244353;
    
    int sgn(double a) { return a < -eps ? -1 : a < eps ? 0 : 1; }
    
    using namespace std;
    
    ll f[maxn][maxn],a[maxn][maxn];
    ll t,n,m;
    
    ll solve(ll h) {
        for (int i = 0;i < n;i++) {
            for (int j = 0;j < m;j++)
                f[i][j] = INF;
        }
        f[0][0] = 0;
        for (int i = 0;i < n;i++) {
            for (int j = 0;j < m;j++) {
                ll v = i + j + h;
                if (a[i][j] < v) {
                    f[i][j] = INF;
                    continue;
                }
                if (j >= 1)
                    f[i][j] = min(f[i][j],f[i][j-1]);
                if (i >= 1)
                    f[i][j] = min(f[i][j],f[i-1][j]);
                f[i][j] += a[i][j] - v;
            }
        }
        return f[n-1][m-1];
    }
    
    int main() {
        ios::sync_with_stdio(false);
        cin >> t;
        while (t--) {
            cin >> n >> m;
            for (int i = 0;i < n;i++) {
                for (int j = 0;j < m;j++)
                    cin >> a[i][j];
            }
            ll ans = INF;
            for (int i = 0;i < n;i++) {
                for (int j = 0;j < m;j++) {
                    ans = min(ans,solve(a[i][j]-i-j));
                }
            }
            cout << ans << endl;
        }
        return 0;
    }
  • 相关阅读:
    JTS相关资料和示例
    微信、支付宝支付那点事
    系统化全方位监控告警,这一篇足矣
    耶鲁大学研究创造了模拟人类认知的计算机芯片
    Docker孵化的5个开源项目
    图解数据中心水系统标准和架构(大全)
    React Native 项目整合 CodePush 全然指南
    1分钟了解MyISAM与InnoDB的索引差异
    Google I/O 官方应用中的动效设计
    为了完毕月入三万的目标,我都做了哪些准备?
  • 原文地址:https://www.cnblogs.com/-Ackerman/p/13193163.html
Copyright © 2011-2022 走看看