HDU 5903 - Square Distance [ DP ] ( BestCoder Round #87 1002 )

题意:   

  给一个字符串t ,求与这个序列刚好有m个位置字符不同的由两个相同的串拼接起来的字符串 s,   

  要求字典序最小的答案
    
分析:   

  把字符串折半,分成0 - n/2-1 和 n/2 - n-1

  dp[i][j] 表示 第i位及之后的总代价为j可不可行   

  从第 n/2-1 位推回第 0 位, 若dp[0][m] = 1,则存在   

  然后贪心对每一位从'a'试到'z',选取接下来存在解的字符

 

 1 #include <cstdio>
 2 #include <algorithm>
 3 #include <iostream>
 4 #include <cstring>
 5 using namespace std;
 6 const int MAXN = 1005;
 7 bool dp[MAXN][MAXN];//dp[i][j] :第i位及之后的总代价为j可不可行 
 8 int t, n, m;
 9 char s[MAXN];
10 int main()
11 {
12     scanf("%d", &t);
13     while (t--)
14     {
15         scanf("%d%d", &n, &m);
16         scanf("%s", s);
17         memset(dp, 0, sizeof(dp));
18         dp[n/2][0] = 1;
19         for (int i = n/2-1; i >= 0; i--)
20         {
21             if (s[i] == s[i+n/2])
22             {
23                 for (int j = 0; j <= m; j++) dp[i][j] = dp[i+1][j];//不改
24                 for (int j = 0; j <= m-2; j++) if (dp[i+1][j]) dp[i][j+2] = 1;//改两个
25             }
26             else
27             {
28                 for (int j = 0; j <= m-1; j++) if (dp[i+1][j]) dp[i][j+1] = 1;//改一个
29                 for (int j = 0; j <= m-2; j++) if (dp[i+1][j]) dp[i][j+2] = 1;//改两个
30             }
31         }
32         if (!dp[0][m])
33         {
34             puts("Impossible"); continue;
35         }
36         int k = m;
37         for (int i = 0; i < n/2; i++)
38         {
39             for (int j = 0; j < 26; j++)
40             {
41                 int p = 0;
42                 if (s[i] != j+'a') p++;
43                 if (s[i+n/2] != j+'a') p++;
44                 if (dp[i+1][k-p])
45                 {
46                     s[i] = j + 'a';
47                     s[i+n/2] = j + 'a';
48                     k -= p;
49                     break;
50                 }
51             }
52         }
53         puts(s);
54     }
55 }

 

posted @ 2016-09-25 14:31  nicetomeetu  阅读(355)  评论(0编辑  收藏  举报