【题意】将字符串A变成字符串B,两种操作:Next,将字符置换成下一个字符('a'>'b','b'>'c'...'y'>'z');Prev,将字符置换成前一个字符('z'>'y','y'>'x'...'b'>'a')。Next和Prev操作的代价不同,求出最小代价,如果不行则返回-1。
【算法】:
1.判断能否由A得到B。如果不能,return -1;
如何判断:可以建立一个二部图。左右两侧的点依次为a、b、c...y、z。(A[i],B[i])代表二部图中的一条边,任意两条边有相交,则A不能得到B。因此判断条件是(A[i]-A[j])*(B[i]-B[j])不能为负,for any i,j。
2.计算代价。
【Java代码】来自菜鸟
1 import java.util.*; 2 import java.util.regex.*; 3 import java.text.*; 4 import java.math.*; 5 6 7 public class NextOrPrev 8 { 9 public int getMinimum(int nextCost, int prevCost, String start, String goal) 10 { 11 char[] s = start.toCharArray(); 12 char[] g = goal.toCharArray(); 13 14 //check if we can get to goal 15 int i,j; 16 for(i=0;i<s.length;i++){ 17 for(j=i+1;j<s.length;j++){ 18 if((s[i]-s[j])*(g[i]-g[j])<0) 19 return -1; 20 } 21 } 22 //compute 23 int count=0; 24 for(i=0;i<s.length;i++){ 25 if(s[i]<g[i]){ 26 count+=nextCost*(g[i]-s[i]); 27 } 28 else{ 29 count+=prevCost*(s[i]-g[i]); 30 } 31 } 32 33 return count; 34 } 35 36 37 } 38 //Powered by KawigiEdit 2.1.4 (beta) modified by pivanof!
【Java代码】来自大神
【分析】他给A[i],B[i]排了序,反映到二部图上来,也是不能有边相交。
public class NextOrPrev { public int getMinimum(int nextCost, int prevCost, String start, String goal) { int length = start.length(); int[] alignStart = new int[length]; int[] alignGoal = new int[length]; int i; int cost = 0; i = 0; for(char c = 'a'; c <= 'z'; c++) { for(int j=0; j<length; j++) { if (start.charAt(j) == c) { alignStart[j] = i++; break; } } } i = 0; for(char c = 'a'; c <= 'z'; c++) { for(int j=0; j<length; j++) { if (goal.charAt(j) == c) { alignGoal[j] = i++; break; } } } for(int j=0; j<length; j++) { int dist; if(alignStart[j] != alignGoal[j]) { return -1; } dist = start.charAt(j) - goal.charAt(j); cost += dist < 0 ? nextCost * dist * -1 : prevCost * dist; } return cost; } }
【C++代码】来自大神
【分析】大神的判断条件,在二部图上反映出来也是两条边不能相交。但不知道大神是否也是用二部图来分析的,是否有更好的想法?
#include<vector> #include<string> #include<algorithm> using namespace std; class NextOrPrev{ public: int getMinimum(int ne,int pr,string st,string go){ int i,j,k,n; n=st.length(); for(i=0;i<n;i++) for(j=0;j<n;j++) if((st[i]<st[j] && go[i]>go[j]) || (st[i]>st[j] && go[i]<go[j])) return -1; int ans=0; for(i=0;i<n;i++) if(st[i]<go[i])ans+=(((int)go[i])-((int)st[i]))*ne; else ans+=(((int)st[i])-((int)go[i]))*pr; return ans; } };
【总结】:通过看大神的代码,自己YY出来的二部图模型,不知道有没有更好的方法。