洛谷9.23

[IOI2000] 回文字串

题目背景

IOI2000 第一题

题目描述

回文词是一种对称的字符串。任意给定一个字符串,通过插入若干字符,都可以变成回文词。此题的任务是,求出将给定字符串变成回文词所需要插入的最少字符数。

比如 Ab3bd \verb!Ab3bd! Ab3bd 插入 2 2 2 个字符后可以变成回文词 dAb3bAd \verb!dAb3bAd! dAb3bAd 或 Adb3bdA \verb!Adb3bdA! Adb3bdA,但是插入少于 2 2 2 个的字符无法变成回文词。

注意:此问题区分大小写。

输入格式

输入共一行,一个字符串。

输出格式

有且只有一个整数,即最少插入字符数。

样例 #1

样例输入 #1

Ab3bd

样例输出 #1

2

提示

数据范围及约定

记字符串长度为 l l l。

对于全部数据, 0 < l ≤ 1000 0<l\le 1000 0<l≤1000。

分析

令 d p [ i ] [ j ] dp[i][j] dp[i][j]表示使坐标从j到i的子串变成回文串所需要的最小字符数,当 s [ i ] = = s [ j ] s[i]==s[j] s[i]==s[j]时,此时可以选择添加,此时需要下表从 i i i到 j + 1 j+1 j+1为回文串,则 d p [ i ] [ j ] = d p [ i ] [ j + 1 ] + 1 dp[i][j]=dp[i][j+1]+1 dp[i][j]=dp[i][j+1]+1,或者不添加,则 d p [ i ] [ j ] = d p [ i − 1 ] [ j + 1 ] dp[i][j]=dp[i-1][j+1] dp[i][j]=dp[i−1][j+1],当 s [ i ] ! = s [ j ] s[i]!=s[j] s[i]!=s[j]时,可以选择在 i i i和 j j j处添加,若在 i i i处添加,此时下标 j + 1 j+1 j+1到 i i i得是回文串,则 d p [ i ] [ j ] = d p [ i ] [ j + 1 ] + 1 dp[i][j]=dp[i][j+1]+1 dp[i][j]=dp[i][j+1]+1,同理在 j j j处添加,则 d p [ i ] [ j ] = d p [ i − 1 ] [ j ] + 1 dp[i][j]=dp[i-1][j]+1 dp[i][j]=dp[i−1][j]+1,最后取最小的即可。

代码

c 复制代码
#include<bits/stdc++.h>
using namespace std;
const int N = 1005, INF = 0x3f3f3f3f;
int dp[N][N];
int main() {
    string s;
    cin >> s;
    int n = s.size();
    for(int i = 1; i <= n; i ++ ) {
        for(int j = i; j >= 1; j -- ) {
            if(s[j - 1] == s[i - 1]) {
                dp[i][j] = min(dp[i][j + 1] + 1, dp[i - 1][j + 1]);
            } else {
                dp[i][j] = min(dp[i - 1][j], dp[i][j + 1]) + 1;
            }
        }
    }
    cout << dp[n][1];
    return 0;
}

[USACO03FALL] Cow Exhibition G

题目背景

题目描述

奶牛想证明它们是聪明而风趣的。为此,贝西筹备了一个奶牛博览会,她已经对 N N N 头奶牛进行了面试,确定了每头奶牛的智商和情商。

贝西有权选择让哪些奶牛参加展览。由于负的智商或情商会造成负面效果,所以贝西不希望出展奶牛的智商之和小于零,或情商之和小于零。满足这两个条件下,她希望出展奶牛的智商与情商之和越大越好,请帮助贝西求出这个最大值。

输入格式

第一行:单个整数 N N N, 1 ≤ N ≤ 400 1 \le N \le 400 1≤N≤400。

第二行到第 N + 1 N+1 N+1 行:第 i + 1 i+1 i+1 行有两个整数: S i S_i Si 和 F i F_i Fi,表示第 i i i 头奶牛的智商和情商,− 1000 ≤ S i ; F i ≤ 1000 1000 \le S_i;F_i \le 1000 1000≤Si;Fi≤1000。

输出格式

输出单个整数:表示情商与智商和的最大值。贝西可以不让任何奶牛参加展览,如果这样做是最好的,输出 0 0 0。

样例 #1

样例输入 #1

5
-5 7
8 -6
6 -3
2 1
-8 -5

样例输出 #1

8

提示

选择第一头,第三头,第四头奶牛,智商和为−5+6+2 = 3,情商和为7−3+1 = 5。再加

入第二号奶牛可使总和提升到10,不过由于情商和变成负的了,所以是不允许的

分析

可以看出这是01背包的变式,令dp[i][j]表示取前i个奶牛,总智商为j的情商的最大值,最后答案只需要遍历所有的dp,获取情商和智商和即可。同普通01背包,状态转移如下

  • dp[i][j]=max(dp[i-1][j],dp[i-1][j-w]+v)

但是这里会出现智商为负的情况,导致数组越界,因此可以将dp数组整体右移4e5个单位,最后二维会MLE,需要滚动数组优化一下,还有一个重点,优化成一维时,若体积为负,则可能超过最大体积,此时需要正着遍历

代码

c 复制代码
#include<bits/stdc++.h>
using namespace std;
const int N = 405, M = 9e5 + 5;
int dp[M]; // dp[i][j] 取i个奶牛,总智商为j,情商的最大值
struct node_ {
    int first, second;
}t[N];
int main() {
    int n;
    cin >> n;
    int maxn = 0;
    memset(dp, -0x3f, sizeof(dp));
    dp[(int)4e5] = 0;
    for(int i = 1; i <= n; i ++ ) {
        cin >> t[i].first >> t[i].second;
        maxn += t[i].first > 0 ? t[i].first : 0;
    }
    for(int i = 1; i <= n; i ++ ) {
        if(t[i].first >= 0) {
            for(int j = 8e5; j >= t[i].first; j -- ) dp[j] = max(dp[j], dp[j - t[i].first] + t[i].second);
        } else {
            for(int j = 0; j <= 8e5 + t[i].first; j ++ ) dp[j] = max(dp[j], dp[j - t[i].first] + t[i].second);
        }
    }
    int res = 0;
    for(int i = 4e5; i <= 8e5; i ++ ) {
        if(dp[i] > 0)
            res = max(res, dp[i] + i - (int)4e5);
    }
    cout << res << endl;
    return 0;
}
相关推荐
南宫生1 小时前
贪心算法习题其四【力扣】【算法学习day.21】
学习·算法·leetcode·链表·贪心算法
Perishell1 小时前
无人机避障——大疆与Airsim中的角速度信息订阅获取
linux·动态规划·无人机
懒惰才能让科技进步1 小时前
从零学习大模型(十二)-----基于梯度的重要性剪枝(Gradient-based Pruning)
人工智能·深度学习·学习·算法·chatgpt·transformer·剪枝
Ni-Guvara2 小时前
函数对象笔记
c++·算法
泉崎2 小时前
11.7比赛总结
数据结构·算法
你好helloworld2 小时前
滑动窗口最大值
数据结构·算法·leetcode
AI街潜水的八角3 小时前
基于C++的决策树C4.5机器学习算法(不调包)
c++·算法·决策树·机器学习
白榆maple3 小时前
(蓝桥杯C/C++)——基础算法(下)
算法
JSU_曾是此间年少3 小时前
数据结构——线性表与链表
数据结构·c++·算法
此生只爱蛋4 小时前
【手撕排序2】快速排序
c语言·c++·算法·排序算法