hdu 1513(滚动数组)

Palindrome

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 4751    Accepted Submission(s): 1625

Problem Description

A
palindrome is a symmetrical string, that is, a string read identically
from left to right as well as from right to left. You are to write a
program which, given a string, determines the minimal number of
characters to be inserted into the string in order to obtain a
palindrome.

As an example, by inserting 2 characters, the string
"Ab3bd" can be transformed into a palindrome ("dAb3bAd" or "Adb3bdA").
However, inserting fewer than 2 characters does not produce a
palindrome.

Input

Your
program is to read from standard input. The first line contains one
integer: the length of the input string N, 3 <= N <= 5000. The
second line contains one string with length N. The string is formed from
uppercase letters from ‘A‘ to ‘Z‘, lowercase letters from ‘a‘ to ‘z‘
and digits from ‘0‘ to ‘9‘. Uppercase and lowercase letters are to be
considered distinct.

Output

Your program is to write to standard output. The first line contains one integer, which is the desired minimal number.

Sample Input

5
Ab3bd

Sample Output

2

Source

IOI 2000

这题用区间DP会爆内存。。正确解法利用LCS解,并且LCS算法算的时候只和当前行和上一行有关,所以利用滚动数组压缩空间

///题意:将一个字符串变成回文串需要添加的最少字符数量
///解法:将字符串反过来.求出原字符串与现在的字符串的LCS,然后用原串减掉LCS的长度即为最少添加的字符
///这个解法的好处就是可以将DP数组变成滚动数组
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<math.h>
#include<algorithm>
using namespace std;
const int N = 5001;
int dp[2][N];
char str[N],str1[N];
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF){
        scanf("%s",str+1);
        for(int i=1;i<=n;i++){
            str1[n-i+1]=str[i];
        }
        ///printf("%s",str1+1);
        memset(dp,0,sizeof(dp));
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                if(str[i]==str1[j]){
                    dp[i%2][j] = dp[(i-1)%2][j-1]+1;
                }else{
                    dp[i%2][j] = max(dp[i%2][j-1],dp[(i-1)%2][j]);
                }
            }
        }
        printf("%d\n",n-max(dp[1][n],dp[0][n]));
    }
}

贴个爆内存的代码。。开short都没用,hdu数据强吗 ORZ ~~~

///题意:将一个字符串变成回文串需要添加的最少字符数量
///解法:区间DP,dp[i][j]代表区间i-j里面要添加多少个字符才能将其变成回文串
///如果 str[i] == str[j] 那么 dp[i][j] = dp[i+1][j-1]
///否则 dp[i][j] = min(dp[i+1][j] ,dp[i][j-1])+1 即考虑是在第i+1个字符之前添加str[j]还是在
///在j-1之后添加字符str[i]
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<math.h>
#include<algorithm>
using namespace std;
const int N = 5000;
short dp[N][N];
char str[N];
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF){
        scanf("%s",str);
        for(int i=1;i<=n;i++) dp[i][i]=0;///区间长度为1的时候不需要添加就是回文串
        for(int l = 2;l<=n;l++){
            for(int i=0;i<=n-l+1;i++){
                int j = i+l-1;
                if(str[i]==str[j]) {
                    dp[i][j] = dp[i+1][j-1];
                }else{
                    dp[i][j] = min(dp[i+1][j],dp[i][j-1])+1;
                }
            }
        }
        printf("%d\n",dp[0][n-1]);
    }
}
时间: 2024-10-31 17:57:52

hdu 1513(滚动数组)的相关文章

HDU - 3033 滚动数组有坑

每层至少一个,滚动时要判上一层非法与否,所以每次都要memset #include<bits/stdc++.h> #define rep(i,j,k) for(int i=j;i<=k;i++) #define rrep(i,j,k) for(int i=j;i>=k;i--) #define scan(a) scanf("%d",&a) using namespace std; const int maxn = 5e5+11; const int oo

HDU 1513 &amp;&amp; POJ 1159 Palindrome (DP+LCS+滚动数组)

题意:给定一个字符串,让你把它变成回文串,求添加最少的字符数. 析:动态规划是很明显的,就是没有了现思路,还是问的别人才知道,哦,原来要么写,既然是回文串, 那么最后正反都得是一样的,所以我们就正反求LCS,这样公共的就求出来了,那么再用总数减掉这个LCS, 那么剩下的肯定就是没有配对的了,就得必须加上了. 思路有了,这里又出现一个问题,这个求LCS,要用的空间复杂度太大了,MLE了...有了思路,还是过不了, 这个题应该用滚动数组来做,我想想在求LCS时,第一维我们只用到了i-1和i,所以呢,

hdu 1513 添最少字回文 (Lcs 滚动数组)

http://blog.csdn.net/ice_crazy/article/details/8244639 这里5000*5000超出内存,所以需要用滚动数组: 用一个now表示当前的结果,pre表示前一个的结果,不断滚动即可 #include <iostream> #include <string> #include <cstring> #include <cstdlib> #include <cstdio> #include <cma

HDU 1024 Max Sum Plus Plus --- dp+滚动数组

HDU 1024 题目大意:给定m和n以及n个数,求n个数的m个连续子系列的最大值,要求子序列不想交. 解题思路:<1>动态规划,定义状态dp[i][j]表示序列前j个数的i段子序列的值,其中第i个子序列包括a[j], 则max(dp[m][k]),m<=k<=n 即为所求的结果 <2>初始状态: dp[i][0] = 0, dp[0][j] = 0; <3>状态转移: 决策:a[j]自己成为一个子段,还是接在前面一个子段的后面 方程: a[j]直接接在前面

HDU 3392 Pie(DP+滚动数组)

题意:有一些男生女生,男生女生数量差不超过100 ,男生女生两两配对.要求求出一种配对方法,使每一对的高度差的和最小. 思路:(我是真的笨笨笨!!磨磨唧唧写一堆是因为我笨!我看了别人的博客,思路全是学别人的,轻喷!)设人少的一组人数为n,b[],人多的一组人数为m,g[](b[],g[]先排好序),用dp[i][j]表示n中的前i个人与m中的前j个人配对所得到的最小值. 那么dp[i][j]就是min(dp[i-1][k]+|b[i]-g[k]|),就是n中前i-1个人和m中前1~k个人配对的最

HDU - 1024 Max Sum Plus Plus(dp+滚动数组优化)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1024 题意:给定n个数字,求其中m段的最大值(段与段之间不用连续,但是一段中要连续) 例如:2 5 1 -2 2 3 -1五个数字中选2个,选择1和2 3这两段. 题解:dp[i][j]从前j个数字中选择i段,然后根据第j个数字是否独立成一段,可以写出 状态转移方程:dp[i][j]=max(dp[i][j-1]+num[j],max(dp[i-1][k])+num[j]) 这里的max(dp[i-

hdu 3392(滚动数组优化dp)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3392 Pie Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 793    Accepted Submission(s): 214 Problem Description A lot of boys and girls come to ou

HDU 5617 Jam&#39;s maze dp+滚动数组

题目链接: hdu: http://acm.hdu.edu.cn/showproblem.php?pid=5617 bc(中文):http://bestcoder.hdu.edu.cn/contests/contest_chineseproblem.php?cid=666&pid=1003 题解: 设dp[x1][x2][i]表示第i步时,从(1,1)点走到了(x1,y1),(n,n)点走到了(x2,y2)点的合法的总数. 1 #include<iostream> 2 #include

[ACM] HDU 4576 Robot (概率DP,滚动数组)

Robot Problem Description Michael has a telecontrol robot. One day he put the robot on a loop with n cells. The cells are numbered from 1 to n clockwise. At first the robot is in cell 1. Then Michael uses a remote control to send m commands to the ro