CodeForces 154A Hometask dp

题目链接:

http://codeforces.com/problemset/problem/154/A

题意:

给你一个字符串,和若干模板串(长度为2),至少删除多少个字母,使得字符串的字串里面没有模板串。

题解:

dp[i][j]表示合法子串s[0...i]的最后一位为j时的最小花费(花费指删除的字母个数)

对每一位考虑删和不删的情况:

如果删,那么它的最后一位一定为之前出现过的。

如果不删,那么s[i]就是最后一位。

考虑这两种情况的转移就可以了。

时间复杂度:O(n*26*26)

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

const int maxn = 1e5 + 10;
const int INF = 0x3f3f3f3f;

int dp[maxn][33];
int cnt[33];
bool mp[33][33];

char str[maxn];
int len, n;

void init() {
    memset(dp, 0x3f, sizeof(dp));
    memset(mp, 0, sizeof(mp));
    memset(cnt, -1, sizeof(cnt));
}

inline int f(char c) {
    return c - ‘a‘ + 1;
}

int main() {
    while (scanf("%s%d", str, &n) == 2) {
        init();
        len = strlen(str);
        char s[11];
        for (int i = 0; i<n; i++) {
            scanf("%s", s);
            mp[f(s[0])][f(s[1])] = mp[f(s[1])][f(s[0])] = 1;
        }
        cnt[f(str[0])] = 0;
        dp[0][f(str[0])] = 0;
        for (int i = 0; i<len; i++) dp[i][0] = i + 1;
        for (int i = 1; i<len; i++) {
            int ch = f(str[i]);
            cnt[ch] = i;
            //第i位删
            for (int j = 1; j <= 26; j++) {
                if (cnt[j] != -1) {
                    int k = cnt[j];
                    dp[i][j] = min(dp[i][j], dp[k][j] + i - k);
                }
            }
            dp[i][ch] = min(dp[i][ch], dp[i - 1][0]);
            //第i位不删
            for (int k = 1; k <= 26; k++) {
                if (mp[k][ch] == 0) {
                    dp[i][ch] = min(dp[i][ch], dp[i - 1][k]);
                }
            }
        }
        int ans = INF;
        for (int i = 1; i <= 26; i++) {
            ans = min(ans, dp[len - 1][i]);
        }
        printf("%d\n", ans);
    }
    return 0;
}
时间: 2024-12-16 19:16:33

CodeForces 154A Hometask dp的相关文章

Codeforces 13C Sequence --DP+离散化

题意:给出一个 n (1 <= n <= 5000)个数的序列 .每个操作可以把 n 个数中的某一个加1 或 减 1.问使这个序列变成非递减的操作数最少是多少 解法:定义dp[i][j]为将前i个数变为以j为结尾的非递减序列的最少操作次数. 则有: dp[i][j] = min(dp[i][j], min(dp[i][k]) + Cost(原来第i个位置上的数转换到j))  (1 <= k <= j) 即前i个数以j结尾的状态可以由前i-1个数以小于等于j的k结尾的状态转移过来,取

Codeforces 77C 树形dp + 贪心

题目链接:点击打开链接 题意: 给定n个点, 每个点的豆子数量 下面是一棵树 再给出起点 每走到一个点,就会把那个点的豆子吃掉一颗. 问:回到起点最多能吃掉多少颗豆子 思路:树形dp 对于当前节点u,先把子节点v都走一次. 然后再往返于(u,v) 之间,直到u点没有豆子或者v点没有豆子. dp[u] 表示u点的最大值.a[u] 是u点剩下的豆子数. #include <cstdio> #include <vector> #include <algorithm> #inc

Codeforces 57C Array dp暴力找规律

题目链接:点击打开链接 先是计算非递增的方案, 若非递增的方案数为x, 则非递减的方案数也是x 答案就是 2*x - n 只需求得x即可. 可以先写个n3的dp,然后发现规律是 C(n-1, 2*n-1) 然后套个逆元即可. #include<iostream> #include<cstdio> #include<vector> #include<string.h> using namespace std; #define ll long long #def

Codeforces 413D 2048(dp)

题目连接:Codeforces 413D 2048 题目大意:2048的游戏,两个相同的数x可以变成一个2*x,先给出n,表示在一个1*n的矩阵上面玩2048,规定每次向左移动,并且每次出现一个,给出序列n,表示出现的块的值,0表示既可以是2也可以是4,问说有多少种可能,使得游戏结束后的最大块的值大于等于2^k. 解题思路:dp[i][j][x]表示第i个位置,值为j,x表示先前有没有出现过大于2^k的数: 这种递增的情况可以直接表示为14(总和,以为后面的2,4如果变大,就肯定能和8想合在一起

Codeforces 455A Boredom (dp)

很裸的dp 状态转移方程 dp[i]=max(dp[i-1],dp[i-2]+dp[i]*i) #include<bits/stdc++.h> using namespace std; long long dp[100020]; int main() { int n,a; scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&a); dp[a]++; } for(int i=2;i&

Codeforces 176B 经典DP

非常好的一个题目,CF上的DP都比较经典 题意就是 给定一个串A,B,正好执行K次操作,每次操作可以把 A串从中间切开,并调换两部分的位置,问最后得到B串共有多少种不同的切法(只要中间有一次不同,即视为不同) 首先,题目的一个关键点一定要抓到,就是 ,不管怎么切 然后调换位置,其实串根本没变,你把串想成一个环,从某一点分成两部分并且交换位置,其实就是把串的起点变到了该点,这是很关键也是最机智的一点 然后,我们要发现规律,你纸上模拟也行,推理也行.. 我们发现:1.首先原串(即以0号字母开头的)个

CodeForces 214B Hometask

本题求n个数组成的大数,要求是2,3,5的倍数. 因为是2 和5 的倍数,所以个位为 0:所以若n个数中没有0,直接输出-1: 难点就是要求为3 的倍数. 因为若某个数为3的倍数,则其各位数的和必然是3的倍数. 当n个数的和为3的倍数时从大到小输出便可: 当n个数的和不为3的倍数时,若n个数中有模3余数与和模3余数相同时,去掉其中最小的,否则去掉两个模3余数不为0且与和模3余数不同的数中最小的.若没有这些数,输出-1: 注意当结果为0时,不能输出前导0: ps:开始写了一个很复杂的代码,后来看过

Nanami&#39;s Digital Board CodeForces - 434B (棋盘dp)

大意: 给定01矩阵, m个操作, 操作1翻转一个点, 操作2求边界包含给定点的最大全1子矩阵 暴力枚举矩形高度, 双指针统计答案 #include <iostream> #include <algorithm> #include <math.h> #include <cstdio> #include <set> #include <map> #include <string> #include <vector>

CodeForces 407B 简单dp

//CodeForces 407B 1 #include "iostream" 2 #include "cstdio" 3 #include "cstring" 4 #include "algorithm" 5 using namespace std; 6 const __int64 mod = 1e9 + 7; 7 __int64 dp[1010]; 8 int pos[1010], n; 9 10 int main() 1