POJ 1159 Palindrome (动态规划)
来源:互联网 发布:php 获取数组相同元素 编辑:程序博客网 时间:2024/06/06 03:42
Description
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
Output
Sample Input
5Ab3bd
Sample Output
2
Source
假设dp[i][j]表示字符串a[i..j]变成palindrome
至少需要花dp[i][j]个操作(i<=j)
那么
如果a[i]=a[j],那么dp[i][j]=dp[i+1][j-1]
否则,就是dp[i][j] = min(dp[i-1][j], dp[i][j-1]) +1 这是因为要在前面或者后面补一个数
初始化为dp[i][i] = 0, dp[i][i+1]= a[i]==a[i+1] ? 0: 1
两种写法:
递归:
int getdp(int i,int j){
if(i == j) return 0;
if(i == j - 1) return a[i]==a[i+1] ? 0 : 2
if(dp[i][j] != -1) return dp[i][j]
if(a[i]==a[j]) return dp[i][j]=getdp(i + 1,j-1)
else return dp[i][j]=min(getdp(i, j-1),getdp(i+1, j))+1
}
递推(i为间隔,间隔小的开始递归)
for(int i = 1;i<= n;i++){
for(int j = 0;j < n - i;j++){
if(a[j]==a[i+j]) dp[j][i+j] =dp[j+1][i+j-1]
else dp[j][i+j]=min(dp[j+1][i+j],dp[j][i+j-1])+1
}
}
注意dp[i][j]的范围i<=j
感想:
1、如果这个题换一种思路还可以用
假设串s和它的逆串s'的最长公共子序列长度为L.
则需要添加的字符个数为 串长s-L。
2、除了用short避免MLE,还可以用dp中常出现的滚动数组或者动态滚动数组
来节省内存。
3、不过递归容易爆栈,斟酌着用。
4、终于搞清楚为什么有时候写的程序用c++提交AC,而用g++提交就wa。
要从计算机原理说起:
内存实际上连续的一片,申请内存的时候,一些语言会强制检查越界,
比如java。c++这个实际上数据就是一个指针,比如dp[0]就是*dp,
dp[1]就是*(dp+1)。如果dp-1这块内存恰好没被使用,那么dp[-1]就不会
报错了。
如果一个二级数组dp的定义是dp[2][4]的话,那么
dp[1][-1]实际上就是dp[0][3],一些编译器会报错,一些不会。
在内存中,二级数据是这么存的:
dp[0][0],dp[0][1],……,dp[0][M-1],dp[1][0],dp[1][1],……
在编译器中,实际上会数组访问这么定位
dp[i][j] = *(dp+i*M+j)
5、最有趣的是我开始把dp的初始条件弄错了,弄成
dp[i][i+1]= (a[i]==a[i+1]?0:2)了,结果用递推写AC了,用递归
却是wa.要不是因为递归wa了,我还不会发现我这里错了。。
因为要加入的字符最少,所以尽管
ab可以加两个字符使之变成abba、bab和aba.但是应该至少是加一个字符。
递推AC代码:
#include<cstdio>#include<iostream>#include<cstring>#include<algorithm>using namespace std;short dp[5005][5005];char a[5010];int main(){ int n,i,j; while(scanf("%d",&n)!=EOF) { getchar(); gets(a); for(i=0;i<n;i++) { dp[i][i]=0; dp[i][i+1]=(a[i]==a[i+1]?0:1); } for(i=1;i<=n;i++) { for(j=0;j<n-i;j++) { if(a[j]==a[j+i]) dp[j][j+i]=dp[j+1][j+i-1]; else dp[j][j+i]=min(dp[j][j+i-1],dp[j+1][j+i])+1; } } printf("%d\n",dp[0][n-1]); } return 0;}//AC//1407MS
递归AC代码:
#include<cstdio>#include<iostream>#include<cstring>#include<algorithm>using namespace std;char a[5005];short dp[5005][5005];short getdp(int i,int j){ if(i==j) return 0; if(i+1==j) return a[i]==a[j]?0:1; if(dp[i][j]!=-1) return dp[i][j]; if(a[i]==a[j]) return dp[i][j]=getdp(i+1,j-1); else return dp[i][j]=min(getdp(i,j-1),getdp(i+1,j))+1;}int main(){ int n; while(scanf("%d",&n)!=EOF) { getchar(); gets(a); memset(dp,-1,sizeof(dp)); printf("%d\n",getdp(0,n-1)); } return 0;}//AC//1438MS
- POJ 1159 Palindrome (动态规划)
- Palindrome POJ 1159 动态规划
- poj 1159 Palindrome 动态规划
- 【动态规划】【poj 1159】palindrome
- poj 1159 palindrome-----动态规划
- POJ 1159 Palindrome(动态规划经典问题)
- POJ-1159-Palindrome-回文-动态规划
- 动态规划——Poj 1159 Palindrome
- POJ 1159 Palindrome 动态规划+滚动数组
- 动态规划+滚动数组 -- POJ 1159 Palindrome
- 动态规划——Poj 1159 Palindrome
- poj 1159 Palindrome -- 回文串,动态规划
- 动态规划——POJ 1159-Palindrome
- POJ 1159 Palindrome(动态规划:最长回文子序列)
- poj 1159 Palindrome 动态规划的三种解法
- POJ1159 Palindrome (动态规划)
- 【POJ 3280】 Cheapest Palindrome(动态规划 回文串)
- POJ 3280 Cheapest Palindrome 动态规划法题解
- android monitor tool (2.0 运行环境)
- storyboard 自定义tableviewcell,cell中的图片 回避重用机制,按照segue跳转
- date得到当前日期
- opencv 光流法对运动目标跟踪Video
- 网易2012校园招聘笔试题目
- POJ 1159 Palindrome (动态规划)
- 简单几步让SecureCRT更舒服【图文并茂】
- 网易2013校园招聘笔试题
- ubuntu12.04中使用有道字典
- 2013-08-17
- java_闭包和回调实现一边按键盘一边演讲
- SQL Server 与 C# 数据类型对照
- 鼠标点击栏目后,栏目的背景效果不能停留,解决方法
- linux tomcat集群配置笔记