POJ - 3280 Cheapest Palindrome 记忆化搜索 DP

Keeping track of all the cows can be a tricky task so Farmer John has installed a system to automate it. He has installed on each cow an electronic ID tag that the system will read as the cows pass by a scanner. Each ID tag's contents are currently a single string with length M (1 ≤ M ≤ 2,000) characters drawn from an alphabet ofN (1 ≤ N ≤ 26) different symbols (namely, the lower-case roman alphabet).

Cows, being the mischievous creatures they are, sometimes try to spoof the system by walking backwards. While a cow whose ID is "abcba" would read the same no matter which direction the she walks, a cow with the ID "abcb" can potentially register as two different IDs ("abcb" and "bcba").

FJ would like to change the cows's ID tags so they read the same no matter which direction the cow walks by. For example, "abcb" can be changed by adding "a" at the end to form "abcba" so that the ID is palindromic (reads the same forwards and backwards). Some other ways to change the ID to be palindromic are include adding the three letters "bcb" to the begining to yield the ID "bcbabcb" or removing the letter "a" to yield the ID "bcb". One can add or remove characters at any location in the string yielding a string longer or shorter than the original string.

Unfortunately as the ID tags are electronic, each character insertion or deletion has a cost (0 ≤ cost ≤ 10,000) which varies depending on exactly which character value to be added or deleted. Given the content of a cow's ID tag and the cost of inserting or deleting each of the alphabet's characters, find the minimum cost to change the ID tag so it satisfies FJ's requirements. An empty ID tag is considered to satisfy the requirements of reading the same forward and backward. Only letters with associated costs can be added to a string.

Input
Line 1: Two space-separated integers:  N and  M 
Line 2: This line contains exactly  M characters which constitute the initial ID string 
Lines 3..  N+2: Each line contains three space-separated entities: a character of the input alphabet and two integers which are respectively the cost of adding and deleting that character.
Output
Line 1: A single line with a single integer that is the minimum cost to change the given name tag.
Sample Input
3 4
abcb
a 1000 1100
b 350 700
c 200 800
Sample Output
900
Hint

If we insert an "a" on the end to get "abcba", the cost would be 1000. If we delete the "a" on the beginning to get "bcb", the cost would be 1100. If we insert "bcb" at the begining of the string, the cost would be 350 + 200 + 350 = 900, which is the minimum.


翻译:

保持对所有奶牛的跟踪是一项棘手的任务,因此农场主约翰已经安装了一个系统来实现自动化。他在每头奶牛身上安装了一个电子ID标签,系统将在奶牛经过扫描仪时读取。每个ID标记是从字母表中提取的一个字符串。

奶牛,它们是淘气的动物,有时试图通过倒着走来欺骗系统。如果一头奶牛的ID是“abcba”,那么无论她怎么走,它都能读到同样的东西,而拥有“abcb”的奶牛可能会注册为两个不同的ID(“abcb”和“bcba”)。

FJ希望改变奶牛的ID标签,这样无论奶牛走过哪个方向,他们都能读到同样的标签。例如,“abcb”可以通过在末尾添加“a”来改变,从而形成“abcba”,这样ID就会是一个回文串。更改ID的其他一些方法包括将三个字母“bcb”添加到“abcb”的开始,以获得ID“bcbabcb”或删除字母“a”以产生ID“bcb”。我们可以在字符串中的任意位置添加或删除字符,其长度比原来的字符串长或短

不幸的是,ID标签是电子信息,每个字符插入或删除都有代价,这取决于要添加或删除的字符值。考虑到奶牛ID标签的内容以及插入或删除字母表中的每个字符的成本,找到更改ID标记的最小成本,从而满足FJ的需求。一个空的ID标签被认为满足了读取前后相同的要求。只有带有相关成本的字母才能添加到字符串中。

Input
Line 1: 两个空间分隔的整数:N和M 
Line 2: 这一行包含了组成初始ID字符串的M个字符 
Lines 3..  N+2: 每行包含三个空间分隔的实体:输入字母和两个整数的字符,分别是添加和删除该字符的成本。
Output
Line 1: 单个整数的一行,这是更改给定名称标签的最小代价。
Sample Input
3 4
abcb
a 1000 1100
b 350 700
c 200 800
Sample Output
900
Hint
如果我们在最后插入一个“a”,得到“abcba”,成本是1000。如果我们在开始的时候删除“a”,就会得到“bcb”,代价就是1100。如果我们在字符串的开始处插入“bcb”,代价将是350 + 200 + 350 = 900,这是最小值。




#include<iostream>
#include<cstdio>
#include<map>
#include<string>
#include<cstring>
using namespace std;
const int len=3e3+5;
#define ll long long
map<char,int>ma;
int dp[len][len];//dp[i][j]从位置i到位置j成回文的最少花费 
string str;
int dfs(int s,int e)
{
	if(s>e)return 0;//边界1:当上一个状态是边界3,可能会出现这种情况 
	if(dp[s][e]!=-1)return dp[s][e];
	if(s==e)return dp[s][e]=0;//边界2:只剩下一个字母了,就是回文 
	if(str[e]==str[s])return dp[s][e]=dfs(s+1,e-1); //边界3: 
	int x=dfs(s+1,e)+ma[str[s]];//删除或添加str[s] 
	int	y=dfs(s,e-1)+ma[str[e]];//删除或添加str[e] 
	dp[s][e]=min(x,y);//取少的 
	return dp[s][e];
}
int main()
{
	int n,m;
	while(cin>>n>>m)
	{
		memset(dp,-1,sizeof(dp));//
		cin>>str;
		int u,v;
		char ch;
		for(int i=0;i<n;++i)
		{
			cin>>ch>>u>>v;
			ma[ch]=min(u,v);//删除和添加的效果是一样的,所以取花费少的 
		}
		cout<<dfs(0,m-1)<<endl;
	}
} 



#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<map>
#include<algorithm>
using namespace std;
#define ll long long
const int mod=1e9;
const int len=2e3+4;
int dp[len][len];
int main()
{
	int n,m;
	cin>>m>>n;
	string str;
	cin>>str;
	char ch;
	int u,v;
	map<char,int>ma;
	while(m--)
	{
		cin>>ch>>u>>v;
		ma[ch]=min(u,v);
	}
	for(int i=n-1;i>=0;--i)
	{
		for(int j=i+1;j<n;++j)
		{
			if(str[i]==str[j])dp[i][j]=dp[i+1][j-1];
			else
			{
				dp[i][j]=min(dp[i+1][j]+ma[str[i]],dp[i][j-1]+ma[str[j]]);
			}
		}
	}
	cout<<dp[0][n-1]<<endl;
} 


猜你喜欢

转载自blog.csdn.net/hutwuguangrong/article/details/80229613