题目:http://acm.hdu.edu.cn/showproblem.php?pid=6739
思路:dp
一个special skill最多有6种排列组合
将前后两个技能进行36种组合配对
即
dp [ i ] [ j ] ( j 为 s [ i ] 的排列组合 0 <= j <= 5 ) = min( dp [ i ] [ j ] , dp [ i - 1 ] [ k ] ( k 为 s [ i - 1 ] 的排列组合 0 <= k <= 5 ) + s [ i - 1 ] 的第 k 种排列组合与是 s [ i ] 的第 j 种排列组合的两个技能连发的最少按键值
#includeusing namespace std; char s[100001]; map<char,int>mp; char p[10][6][4]={ "QWE","QEW","WQE","WEQ","EQW","EWQ", "WWW","WWW","WWW","WWW","WWW","WWW", "WEE","WEE","EWE","EEW","EWE","EEW", "QEE","QEE","EQE","EEQ","EQE","EEQ", "QQE","QEQ","QQE","QEQ","EQQ","EQQ", "EEE","EEE","EEE","EEE","EEE","EEE", "QQW","QWQ","QQW","QWQ","WQQ","WQQ", "QWW","QWW","WQW","WWQ","WQW","WWQ", "QQQ","QQQ","QQQ","QQQ","QQQ","QQQ", "WWE","WEW","WWE","WEW","EWW","EWW", }; int dp[100001][6]; int cmp(int a,int b,int c,int d) { if(!strcmp(p[a][b],p[c][d])) return 0; else if(p[a][b][1]==p[c][d][0]&&p[a][b][2]==p[c][d][1]) return 1; else if(p[a][b][2]==p[c][d][0]) return 2; return 3; } int main() { mp['B']=0,mp['C']=1,mp['D']=2,mp['F']=3,mp['G']=4,mp['T']=5,mp['V']=6,mp['X']=7,mp['Y']=8,mp['Z']=9; while(~scanf("%s",s)) { for(int i=0;s[i];i++) for(int j=0;j<6;j++) dp[i][j]=(i+1)*3+i+1; for(int i=0;i<6;i++) dp[0][i]=3; for(int i=1;s[i];i++) for(int j=0;j<6;j++) for(int k=0;k<6;k++) dp[i][j]=min(dp[i][j],dp[i-1][k]+cmp(mp[s[i-1]],k,mp[s[i]],j)); int minn=0x3f3f3f3f; for(int i=0;i<6;i++) minn=min(minn,dp[strlen(s)-1][i]); printf("%d\n",minn+strlen(s)); } return 0; }