zoukankan      html  css  js  c++  java
  • 01限定串(传纸条模型)⭐

    题目描述

    我们称两个字符串是相似的,当且仅当它们的成分相同,并且组成各成分出现的数目相同。例如字符串"abbcdf"与字符串"bcfdab"就是相似的,而"abbcdf"与"abcdf"不相似,因为它们虽然成分相同,但是各成分出现的次数不同。

    牛牛本来有两个长度均为n的01字符串s,t,但是t串由于数据损坏,导致一些位置不确定到底是0还是1,不过好在,牛牛清楚的记得t串中有(cnt_{0})个0, (cnt_{1})个1

    接下来牛牛要还原损坏的t串。

    s串和t串每存在一个非空相似前缀得分(val_{0}), 每存在一个非空相似后缀得分(val_{1})

    想要知道它能够还原的t串中的最小得分与最大得分。

    输入描述:

    第一行输入五个整数n (cnt_{0}) (cnt_{1}) (val_{0}) (val{1})

    接下来输入两行表示字符串s,t,|s|=|t|=n, n<= 100

    其中,s串完全由'0','1'组成,t串完全由'0','1','?'组成。

    ?表示损坏的部分,也就是需要你还原的部分。

    输入数据保证至少存在一种合法的方案。

    输出描述:

    请输出两个整数,表示还原后的最小得分与最高得分。

    示例1

    输入

    8 6 2 1 1
    10110011
    ????????
    

    输出

    0 4
    

    说明

    可以构造01串t="00011000"达到最小得分(与s串没有相似的前缀与后缀)
    可以构造01串t="00000011"(4个相似的后缀)达到最大得分。

    示例2

    输入

    20 1 19 55 97
    11111010101111111111
    1?????1?1?1????????1
    

    输出

    566 1439
    

    说明

    最小:"11111111111111111101"
    最大:"11111111101111111111"

    示例3

    输入

    1 0 1 -999 1000
    0
    ?
    

    输出

    0 0
    

    说明

    因为限制条件为必须有1个1,所以?处只能填1

    题解

    本题给定了0和1的数量,让你如何排列才能使分数最优。

    我们先考虑问题的简单版本,如果给定字符串t全为问号,即对组成的字符串不加限制,就转变经典传纸条问题,

    即只求一条从(0,0)到(cnt0,cnt1)的路径,只能向右或向下走,使得路径上的点的权值和最大。

    显而易见的变化中的量就是坐标(x,y),用dp[x][y]来表示传到(x,y)这个坐标的时候,最大(小)的权值和

    就是普通的传纸条模型

    但是有的位置给定了你方向(t[i] != '?'), 分四种情况就行

    传统传纸条是

    for (int step = 1; step <= n; ++step)
          for (int i = 0; i <= a; ++i)
          {
                int j = step - i;
                if (判断状态是否合法) continue;
                ...
          }
    

    但是注意到后效性

    也可以直接二维枚举

    #include<bits/stdc++.h>
    #define rep(i,a,b) for(int i=a;i<=b;++i)
    using namespace std;
    
    const int maxn = 1e3 + 5;
    
    int n, a, b, x, y;
    int sum[maxn << 1], f1[maxn][maxn], f2[maxn][maxn];
    string s,t;
    
    int main()
    {
        cin >> n >> a >> b >> x >> y >> s >> t;
        s = " " + s; t = " " + t;
        rep(i, 1, n) sum[i] = sum[i - 1] + s[i] - '0',
    
        memset(f1, 0xcf, sizeof f1); memset(f2, 0x3f, sizeof f2);
        f1[0][0] = f2[0][0] = y * (sum[n] == b);
    
        rep (i, 0, n)
            rep (j, 0, n)
            {
                int pos = i + j;
                int cur = x * (sum[pos] == j && pos) + 
                    y * (sum[n] - sum[pos] == b - j && pos != n);
            
                if (t[pos] != '0' && j)
                {
                    f1[i][j] = max(f1[i][j], f1[i][j - 1] + cur);
                    f2[i][j] = min(f2[i][j], f2[i][j - 1] + cur); 
                }
    
                if (t[pos] != '1' && i)
                {
                    f1[i][j] = max(f1[i][j], f1[i - 1][j] + cur);
                    f2[i][j] = min(f2[i][j], f2[i - 1][j] + cur); 
                }
            }
         
        cout << f2[a][b] << " " << f1[a][b] << endl;
        return 0;
    } 
    
  • 相关阅读:
    轻重搭配
    EF的优缺点
    使用bootstrap-select有时显示“Nothing selected”
    IIS发布 HTTP 错误 500.21
    js添加的元素无法触发click事件
    sql server查看表是否死锁
    sql server把一个库表的某个字段更新到另一张表的相同字段
    SQLSERVER排查CPU占用高的情况
    SQL server中如何按照某一字段中的分割符将记录拆成多条
    LINQ to Entities does not recognize the method 'System.DateTime AddDays(Double)' method, and this method cannot be translated into a store expression.
  • 原文地址:https://www.cnblogs.com/2aptx4869/p/12871558.html
Copyright © 2011-2022 走看看