https://leetcode-cn.com/problems/minimum-distance-to-type-a-word-using-two-fingers/
dp【位置】【手指1 x】【手指1 y】【手指2 x】【手指2 y】,表示已输入该位置后的字符后两只手指所在的位置所用最小的移动距离。由于最开始的时候手指可以位于任何地方,所以dp[-1][所有位置1][所有位置2]=0,未输入任何字符,所以是-1。
由于每次都可以由左手或右手输入。
class Solution {
public:
vector<string> keyboard;
map<char,pair<int,int>> charpos_map;
int dp[305][5][6][5][6];
const int INF=0x3f3f3f3f;
void init(){
keyboard.push_back("ABCDEF");
keyboard.push_back("GHIJKL");
keyboard.push_back("MNOPQR");
keyboard.push_back("STUVWX");
keyboard.push_back("YZ");
for(int i=0;i<keyboard.size();i++){
for(int j=0;j<keyboard[i].size();j++){
charpos_map[keyboard[i][j]]=make_pair(i,j);
}
}
memset(dp,0x3f,sizeof(dp));
}
int dist(int x1,int y1,int x2,int y2){
return abs(x1-x2)+abs(y1-y2);
}
int minimumDistance(string word) {
init();
int n_row=5;
int n_col=6;
for(int i=0;i<word.size();i++){
for(int x1=0;x1<n_row;x1++){
for(int y1=0;y1<n_col;y1++){
for(int x2=0;x2<n_row;x2++){
for(int y2=0;y2<n_col;y2++){
auto new_pos=charpos_map[word[i]];
int new_x=new_pos.first;
int new_y=new_pos.second;
if(i-1<0){
dp[i][new_x][new_y][x2][y2]=min(dp[i][new_x][new_y][x2][y2],dist(new_x,new_y,x1,y1));
dp[i][x1][y1][new_x][new_y]=min(dp[i][x1][y1][new_x][new_y],dist(new_x,new_y,x2,y2));
}
else{
dp[i][new_x][new_y][x2][y2]=min(dp[i][new_x][new_y][x2][y2],dp[i-1][x1][y1][x2][y2]+dist(new_x,new_y,x1,y1));
dp[i][x1][y1][new_x][new_y]=min(dp[i][x1][y1][new_x][new_y],dp[i-1][x1][y1][x2][y2]+dist(new_x,new_y,x2,y2));
}
}
}
}
}
}
int ans=INT_MAX;
auto pos=charpos_map[word[word.size()-1]];
int end_x=pos.first;
int end_y=pos.second;
for(int x=0;x<n_row;x++){
for(int y=0;y<n_col;y++){
ans=min(ans,dp[word.size()-1][x][y][end_x][end_y]);
ans=min(ans,dp[word.size()-1][end_x][end_y][x][y]);
}
}
return ans;
}
};