标签:
小M是一位远近闻名的庄园主。因为近来牛肉涨价,精明小M决定开始养牛。为了方便跟踪所有的牛,小M在庄园上装了一套自动系统。他给了每一个头牛一个电子牌号。当牛走过这个系统时,牛的名字将被自动读入。
每一头牛的电子名字是一个长度为M的,由N个不同小写字母构成的字符串。
很快,淘气的牛找到了系统的漏洞:它们可以倒着走过读码器。一头名字为abcba不会导致任何问题,但是名为abcb的牛会变成两头牛(abcb和bcba)。
于是乎小M决定给牛们改名字,使得牛的名字正读和反读都一样。小M可以在任意位置添加或删除字母。但是,添加和删除每一个字母都有一定的费用。对于一个牛的名字和所有添加或删除字母的费用,找出修改名字的最小的费用。
注意:空字符串也是一个合法的名字。
第一行:两个用空格分开的数,N和M。
第二行:M个字符,初始的牛的名字。
第3到N+2行:每行含有一个字母和两个整数,分别是添加和删除这个字母的费用。
0≤N≤26,0≤M≤2000 , 0≤费用≤10000
一个整数,改变所有名字的最小费用。
3 4
abcb
a 1000 1100
b 350 700
c 200 800
900
==========================================================================================================
开始用的就是简单的递归算法,然后没有通过,最终用动态规划解决了。思想就是从两边开始遍历字符串,通过比较确定添加或删除哪边的字符。
代码如下:
1 //小M家的奶牛 2 #include <iostream> 3 #include <string> 4 #include <vector> 5 using namespace std; 6 7 8 int clist[26]; 9 vector<vector<int> >state; // 动态规划,记录状态 10 string ori_name; 11 int N,M; 12 int CalCost(int,int); 13 int main(){ 14 15 cin>>N>>M>>ori_name; 16 state.resize(M); 17 for (int i=0;i<M;++i) state.at(i).resize(M,-1); 18 19 for (int i=0;i<N;++i) { 20 int acost,dcost; 21 char cha; 22 cin>>cha>>acost>>dcost; 23 clist[cha-‘a‘] = acost<dcost ? acost:dcost; 24 } 25 int min_cost = CalCost(0,M-1); 26 cout<<min_cost; 27 28 return 0; 29 } 30 int CalCost(int l,int r) { 31 int i,tem_cost1,tem_cost2; 32 char left,right; 33 34 if (l>=r) return 0; 35 if (ori_name[l]==ori_name[r]) return CalCost(++l,--r); 36 if (state.at(l).at(r)>=0) return state.at(l).at(r); 37 left = ori_name[l] - ‘a‘; 38 right = ori_name[r] - ‘a‘; 39 tem_cost1 = clist[left] + CalCost(l+1,r); 40 tem_cost2 = clist[right] + CalCost(l,r-1); 41 int min_cost = tem_cost1<tem_cost2 ? tem_cost1:tem_cost2; 42 state.at(l).at(r) = min_cost; 43 return min_cost; 44 }
标签:
原文地址:http://www.cnblogs.com/wenma/p/4476297.html