zoukankan      html  css  js  c++  java
  • NYOJ 1023 还是回文

    还是回文

    时间限制:2000 ms  |  内存限制:65535 KB
    难度:3
     
    描述

    判断回文串很简单,把字符串变成回文串也不难。现在我们增加点难度,给出一串字符(全部是小写字母),添加或删除一个字符,都会产生一定的花费。那么,将字符串变成回文串的最小花费是多少呢?

     
    输入
    多组数据
    第一个有两个数n,m,分别表示字符的种数和字符串的长度
    第二行给出一串字符,接下来n行,每行有一个字符(a~z)和两个整数,分别表示添加和删除这个字符的花费
    所有数都不超过2000
    输出
    最小花费
    样例输入
    3 4
    abcb
    a 1000 1100
    b 350 700
    c 200 800
    样例输出
    900
    上传者
    ACM_马振阳

    解题:转载一下别人的思路。。。

    dp[i][j]代表区间i到区间j成为回文串的最小代价,那么对于dp[i][j]有三种情况:

    1、dp[i+1][j]表示区间i到区间j已经是回文串了的最小代价,那么对于s[i]这个字母,我们有两种操作,删除与添加,对应有两种代价,dp[i+1][j]+add[s[i]],dp[i+1][j]+del[s[i]],取这两种代价的最小值;

    2、dp[i][j-1]表示区间i到区间j-1已经是回文串了的最小代价,那么对于s[j]这个字母,同样有两种操作,dp[i][j-1]+add[s[j]],dp[i][j-1]+del[s[j]],取最小值

    3、若是s[i]==s[j],dp[i+1][j-1]表示区间i+1到区间j-1已经是回文串的最小代价,那么对于这种情况,我们考虑dp[i][j]与dp[i+1][j-1]的大小........

    然后dp[i][j]取上面这些情况的最小值.........


    先上挫一点的代码,可以AC的但是速度比较慢
     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <cstdlib>
     5 #include <vector>
     6 #include <climits>
     7 #include <algorithm>
     8 #include <cmath>
     9 #define LL long long
    10 using namespace std;
    11 int dp[2010][2010];
    12 int main() {
    13     int m,len,i,j,a,b,temp,temp2;
    14     char s[2010],t[10];
    15     int add[30],del[30];
    16     while(~scanf("%d %d",&m,&len)) {
    17         scanf("%s",s);
    18         for(i = 0; i < m; i++) {
    19             scanf("%s %d %d",t,&a,&b);
    20             add[t[0]-'a'] = a;
    21             del[t[0]-'a'] = b;
    22         }
    23         for(i = len-2; i >= 0; i--){
    24             for(j = i+1; j < len; j++){
    25                 dp[i][j] = min(dp[i+1][j]+del[s[i]-'a'],dp[i+1][j]+add[s[i]-'a']);
    26                 temp = min(dp[i][j-1]+del[s[j]-'a'],dp[i][j-1]+add[s[j]-'a']);
    27                 dp[i][j] = min(dp[i][j],temp);
    28                 if(s[i] == s[j]) dp[i][j] = min(dp[i][j],dp[i+1][j-1]);
    29             }
    30         }
    31         printf("%d
    ",dp[0][len-1]);
    32     }
    33     return 0;
    34 }
    View Code
    
    

    这个是优化的过代码。优化之后,速度真心快了很多啊。
     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <cstdlib>
     5 #include <vector>
     6 #include <climits>
     7 #include <algorithm>
     8 #include <cmath>
     9 #define LL long long
    10 using namespace std;
    11 int dp[2010][2010];
    12 int main() {
    13     int m,len,i,j,a,b,temp,temp2;
    14     char s[2010],t[5];
    15     int cost[30];
    16     while(~scanf("%d %d",&m,&len)) {
    17         scanf("%s",s);
    18         for(i = 0; i < m; i++) {
    19             scanf("%s %d %d",t,&a,&b);
    20             cost[t[0]-'a'] = min(a,b);
    21         }
    22         for(i = len-2; i >= 0; i--){
    23             for(j = i+1; j < len; j++){
    24                 dp[i][j] = min(dp[i+1][j]+cost[s[i]-'a'],dp[i][j-1]+cost[s[j]-'a']);
    25                 if(s[i] == s[j]) dp[i][j] = min(dp[i][j],dp[i+1][j-1]);
    26             }
    27         }
    28         printf("%d
    ",dp[0][len-1]);
    29     }
    30     return 0;
    31 }
    View Code
    
    
    
     
  • 相关阅读:
    Gym-102040B Counting Inversion
    hdu 6899 Xor
    CSPS2019游记
    [网络流系列]网络流基础
    [线段树系列]几道不错的线段树题目题解
    浅谈矩阵[简洁易懂]——上篇
    DP动态规划学习笔记——高级篇上
    DP动态规划学习笔记
    [点分治系列] 静态点分
    [数论系列] 素数篇
  • 原文地址:https://www.cnblogs.com/crackpotisback/p/3850755.html
Copyright © 2011-2022 走看看