SRM 509 DIV1 500pt(DP)

题目简述

给定一个字符串,可以对其进行修改,删除,增加操作,相应的操作有对应的花费,要求你用最小的花费把字符串变为回文串

题目做法

先搞一遍floyed把各种操作的最小花费求出来,然后就是类似编辑距离的DP了,这题坑了好久。。。中间结果会爆int,我设置的inf=0x3f3f3f3f,中间结果有inf+inf+inf..刚开始dp数组是int型的。。。这里搞了好几才发现这问题。。。西安现场赛也遇到这个问题了。。。然后也是浪费了将近100分钟的时间。。。导致后面做题的时间不够了。。。

代码:

 1 #define maxn 30
 2 int changeCost[maxn][maxn], addCost[maxn], eraseCost[maxn];
 3 LL dp[55][55];
 4 class PalindromizationDiv1
 5 {
 6 public:
 7     int getMinimumCost(string word, vector <string> operations)
 8     {
 9         memset(changeCost, 0x3f, sizeof(changeCost));
10         memset(addCost, 0x3f, sizeof(addCost));
11         memset(eraseCost, 0x3f, sizeof(eraseCost));
12         for (int i = 0; i < operations.size(); i++)
13         {
14             stringstream ss(operations[i]);
15             string s;
16             char a, b;
17             int num;
18             ss >> s;
19             if (s == "add")
20             {
21                 ss >> a >> num;
22                 addCost[a - ‘a‘] = num;
23             }
24             if (s == "erase")
25             {
26                 ss >> a >> num;
27                 eraseCost[a - ‘a‘] = num;
28             }
29             if (s == "change")
30             {
31                 ss >> a >> b >> num;
32                 changeCost[a - ‘a‘][b - ‘a‘] = num;
33             }
34         }
35         for (int i = 0; i < 26; i++) changeCost[i][i] = 0;
36         for (int k = 0; k < 26; k++)
37             for (int i = 0; i < 26; i++)
38                 for (int j = 0; j < 26; j++)
39                 {
40                     if (i == j || j == k || i == k) continue;
41                     changeCost[i][j] = min(changeCost[i][j], changeCost[i][k] + changeCost[k][j]);
42                 }
43
44         for (int i = 0; i < 26; i++)
45             for (int j = 0; j < 26; j++)
46             {
47                 addCost[i] = min(addCost[i], addCost[j] + changeCost[j][i]);
48                 eraseCost[i] = min(eraseCost[i], changeCost[i][j] + eraseCost[j]);
49             }
50         int n = word.size();
51         memset(dp, 0x3f, sizeof(dp));
52         for (int i = n - 1; i >= 0; i--)
53         {
54             dp[i][i] = dp[i][i - 1] = 0;
55             for (int j = i + 1; j < n; j++)
56             {
57                 int a = word[i] - ‘a‘, b = word[j] - ‘a‘;
58                 dp[i][j] = min(dp[i][j], dp[i + 1][j] + eraseCost[a]);
59                 dp[i][j] = min(dp[i][j], dp[i][j - 1] + eraseCost[b]);
60                 for (int k = 0; k < 26; k++)
61                 {
62                     dp[i][j] = min(dp[i][j], dp[i + 1][j] + addCost[k] + changeCost[a][k]);
63                     dp[i][j] = min(dp[i][j], dp[i][j - 1] + addCost[k] + changeCost[b][k]);
64                     dp[i][j] = min(dp[i][j], dp[i + 1][j - 1] + changeCost[a][k] + changeCost[b][k]);
65                 }
66             }
67         }
68         LL ret = dp[0][n - 1];
69         return ret >= INF ? -1 : (int)ret;
70     }
71 };

时间: 2024-08-02 05:07:04

SRM 509 DIV1 500pt(DP)的相关文章

SRM 502 DIV1 500pt(DP)

题目简述 给定比赛时间T和n个题目,你可以在任意时间提交题目,每个题目有一个初始分数maxPoints[i],每个单位时间题目的分数将会减少pointsPerMinute[i],即如果在时间t解决了第i个题目,那么获得的分数为maxPoints[i] - t * pointsPerMinute[i],另外做每个题目需要requiredTime[i]的时间,求能够获得的最大分数是多少? 题解 由于问题解决的先后,获得的分数是不一样的,因为我们首先得确定做题的选择顺序,根据相邻交换法,对于问题a和问

SRM 514 DIV1 500pt(DP)

题目简述 给定一个H×W大小的矩阵,每个格子要么是1~9中的一个数,要么是".",要求你把“.”填成具体的数字(1~9),并且符合以下两个要求: 对于所有的整数r 和 c( 0 <= r <= H-n,0 <= c < W), 使得 F[r][c] + F[r+1][c] + ... + F[r+n-1][c] 是奇数. 对于所有的整数 r 和c(0 <= r < H,0 <= c <= W-m), 使得 F[r][c] + F[r][c

SRM 508 DIV1 500pt(DP)

题目简述 给定一个大小为 n的序列(n<=10)R,要求你计算序列A0, A1, ..., AN-1的数量,要求A序列满足A0 + A1 + ... + AN-1 = A0 | A1 | ... | AN-1(0<=Ai<=R[i]) 题解 把n个数看成二进制,如果要求n个数的和等于n个数的或值,那么对于n个数的每一位,最多只可能有一个1,因为超过一个一就会产生进位. 由于第i个数如果当前位放置的是0,但 R[i]的当前位是1,那么之后的位置上就可以随意放了,没有限制,所以我们可以用DP

SRM 511 DIV1 500pt(DP)

题目简述 给定n个数,两个人轮流取数,和之前两个人的取的数或起来,谁不能取数或者谁取到的数和之前的数或值为511谁输,问谁能够赢? 题解 刚开始的想法是直接搜,不过需要记录取过的值的状态,2^50显然超时...对于当前或值cur,或上一个数num,只有两种情况,要么是 cur|num==cur, 对于这种数,只是把这个状态直接给下一个玩家,起到延缓一步的作用,他们的选取顺序对局面没有影响,可以先全部轮流取掉,如果这种数的个数大于当前已经取的数的数量,那么我们还可以选择这种数,如果选择这个数可以导

SRM 618 DIV1 500

非常棒的组合问题,看了好一会,无想法.... 有很多做法,我发现不考虑顺序的最好理解,也最好写. 结果一定是两种形式 A....A   dp[n-1] A...A...A sgma(dp[j]*dp[n-j-1])( 1<=j<=n-2) 最后乘上n! 什么时候才能自己在比赛中做出一个500分来啊!!! class LongWordsDiv1 { public : int count(int n) { int i,j; fact[0] = 1; for(i = 1; i <= n; i

Topcoder SRM 643 Div1 250&lt;peter_pan&gt;

Topcoder SRM 643 Div1 250 Problem 给一个整数N,再给一个vector<long long>v; N可以表示成若干个素数的乘积,N=p0*p1*p2*......*pn,我们假设p0,p1,...,pn是单调不降的,那么v里存储的是下标为偶数 的N的质因数p0,p2,p4,...,p(2k).现在要求写一个程序,返回一个vector<long long>ans; ans里存储的是p0,p1,p2,...,pn. Limits Time Limit(m

SRM 631 DIV1

SRM 631 DIV1 A:最多肯定只需要两步,中间的两行,一行黑,一行白就可以了,这样的话,只需要考虑一开始就满足,和枚举一行去染色满足的情况就可以了,暴力即可 B:贪心,一个记录当前有猫的位置和当前超过一只猫的位置,然后位置排序从左往右找,如果当前能移动到之前超过两只的位置,就全部移动过去,不增加,如果不行,那么考虑当前这个能不能铺成一条,如果可以,相应更新位置,如果不行,就让猫全部堆到右边右边去,然后堆数多1 代码: A: #include <iostream> #include &l

SRM 622 div1 250

Problem Statement    In the Republic of Nlogonia there are N cities. For convenience, the cities are numbered 0 through N-1. For each two different cities i and j, there is a direct one-way road from i to j. You are given the lengths of those roads a

SRM 587 DIV1

550 结论:同一层的交点共线. 很容易猜到,也可以跑几组数据验证. 利用结论就可以按层算,再利用对称性简化计算. 1 using namespace std; 2 #define maxn 70100 3 class TriangleXor { 4 public: 5 int theArea(int); 6 }; 7 double l[maxn] , x[maxn] , y[maxn] , H; 8 int idx; 9 10 void addpoint(double k,double w)