• hdu 5903 Square Distance(dp)


    Problem Description
    A string is called a square string if it can be obtained by concatenating two copies of the same string. For example, "abab", "aa" are square strings, while "aaa", "abba" are not.

    Hamming distance between two strings of equal length is the number of positions at which the corresponding symbols are different.

    Peter has a string s=s1s2...sn of even length. He wants to find a lexicographically smallest square string t=t1t2...tn that the hamming distance between s and t is exact m. In addition, both s and t should consist only of lowercase English letters.
     
    Input
    There are multiple test cases. The first line of input contains an integer T, indicating the number of test cases. For each test case:

    The first contains two integers n and m (1n1000,0mn,n is even) -- the length of the string and the hamming distance. The second line contains the string s.
     
    Output
    For each test case, if there is no such square string, output "Impossible" (without the quotes). Otherwise, output the lexicographically smallest square string.

    题意:给你一个长度为n的s串,一个数m,现在让你构造一个长度也为n的t串,使这个串是由两个相同的串拼起来的,并且和s串对应的位不同的数量为m。

    而且使t的字典序尽量小。

    一开始会想到贪心,但是显然单纯的贪心无法得到正确结果。于是要利用到dp

    dp[i][count]表示取到i位有count个位置不一样是否成立。dp[i][count]+=dp[i+1][count-gg](gg表示要变的位置数)

    这题要分几种情况

    (1)s[i]==s[i+n/2],这个时候要么不变位置要么就变2次。

    (2)s[i]!=s[i+n/2],这是要么变2次要么变1次。

    由于要求字典序要最小,所以尽量要从首位开始变。于是递推要从n/2开始,这样才能保证前面的操作能使后续操纵成立。

    #include <iostream>
    #include <cstring>
    using namespace std;
    char s[1010];
    int dp[1010][1010];
    int main()
    {
        int t;
        cin >> t;
        while(t--) {
            int n , m;
            cin >> n >> m;
            cin >> (s + 1);
            int count = m;
            memset(dp , 0 , sizeof(dp));
            dp[n / 2 + 1][0] = 1;
            for(int i = n / 2 ; i >= 1 ; i--) {
                if(s[i] == s[i + n / 2]) {
                    for(int j = 0 ; j <= m ; j++) {
                        dp[i][j] += dp[i + 1][j];
                    }
                    for(int j = 2 ; j <= m ; j++) {
                        dp[i][j] += dp[i + 1][j - 2];
                    }
                }
                else {
                    for(int j = 1 ; j <= m ; j++) {
                        dp[i][j] += dp[i + 1][j - 1];
                    }
                    for(int j = 2 ; j <= m ; j++) {
                        dp[i][j] += dp[i + 1][j - 2];
                    }
                }
            }
            if(!dp[1][m]) {
                cout << "Impossible" << endl;
                continue;
            }
            for(int i = 1 ; i <= n / 2 ; i++) {
                for(int j = 0 ; j < 26 ; j++) {
                    int temp = (s[i] != j + 'a') + (s[i + n / 2] != j + 'a');
                    if(dp[i + 1][m - temp]) {
                        s[i] = s[i + n / 2] = j + 'a';
                        m -= temp;
                        break;
                    }
                }
            }
            cout << s + 1 << endl;
        }
        return 0;
    }
    
  • 相关阅读:
    Linux下压缩解压缩命令
    Linux挂载外部设备
    Ubuntu下安装软件的三种方式
    Linux查看和修改文件权限
    Linux命令行基础操作
    window下常用的cmd命令
    圆角进度条,带数字居中显示的圆角进度条
    上下滑动控件
    window下Jekyll+github搭建自己的博客
    PAT 团体程序设计天梯赛 L1-046 整除光棍(模拟除法)
  • 原文地址:https://www.cnblogs.com/TnT2333333/p/6058747.html
Copyright © 2020-2023  润新知