题目大意:
输入区有六个数字和一个光标(光标开始时位于第一个数),使用以下六种操作将其变为目标数字,求最少操作数:
1.Swap0:将光标所在数字和第一个数交换
2.Swap1:将光标所在数字和最后一个数交换
3.Up:给光标所在数字+1
4.Down:给光标所在数字-1
5.Left:光标左移
6.Right:光标右移
分析:
这道题做得很失败,一开始想当然的剪枝,认为2-5的四个数字只要和目标数字不同,就没必要移动光标,居然还A了。。数据太水。后来看一个dalao博客给出的一组数据,000159 000519,最小操作数是8,即交换19、51、95,光标是可以移动的嘛!
正解:
将操作分为两类,只有Up/Down可以改变数字的值,剩下四种操作实际上只能改变给定数字的相对位置。把六个数字的位置、光标位置和已访问的数字(只有光标访问过的数字才能用Up/Down改变)作为状态,一遍BFS搜出所有可能的组合,再加上与每一位目标数字之差的绝对值的和(即Up/Down次数)就是答案了。
注意:光标的访问状态只有十种,第一位一定会被访问,而且只有Right和Swap1可以访问未访问过的位置
代码:
#include <iostream> #include <queue> #include <vector> #include <cmath> using namespace std; bool vis[6][6][6][6][6][6][6][10] = {0};//0-5分别对应输入区6个数字的位置,6表示下标位置,7表示下标访问状态 bool list[10][6] = {{1,0,0,0,0,0},//只有Right或Swap1可以访问未访问过的位置,所以只有10种访问状态 {1,0,0,0,0,1}, {1,1,0,0,0,0}, {1,1,0,0,0,1}, {1,1,1,0,0,0}, {1,1,1,0,0,1}, {1,1,1,1,0,0}, {1,1,1,1,0,1}, {1,1,1,1,1,0}, {1,1,1,1,1,1}}; struct node{//分别是 下标位置,访问状态,步数,6个数字的位置 int pos; int state; int d; vector<int> n; }; int main(){ int i, j, a[6] = {0}, b[6] = {0}, ts, min = 0x7FFFFFFF, r; string sa, sb; cin >> sa >> sb; for (i = sa.size()-1, j = 5; i >= 0; i--, j--) a[j] = sa[i]-'0'; for (i = sb.size()-1, j = 5; i >= 0; i--, j--) b[j] = sb[i]-'0'; queue<node> q; int init[6] = {0, 1, 2, 3, 4, 5}; vector<int> t; q.push((node){0, 0, 0, vector<int>(init, init+6)}); vis[0][1][2][3][4][5][0][0] = 1; while (!q.empty()){ node f = q.front(); q.pop(); //根据当前状态计算所需Up/Down次数 r = f.d; for (i = 0; i < 6; i++){ if (list[f.state][i]) r += fabs(a[f.n[i]]-b[i]); else if (a[f.n[i]] != b[i]){ r = 0x7FFFFFFF; break; } } if (r < min) min = r; //Swap0 t = f.n; t[0] = f.n[f.pos];//交换 t[f.pos] = f.n[0]; if (!vis[t[0]][t[1]][t[2]][t[3]][t[4]][t[5]][f.pos][f.state]){ q.push((node){f.pos, f.state, f.d+1, t}); vis[t[0]][t[1]][t[2]][t[3]][t[4]][t[5]][f.pos][f.state] = 1; } //Swap1 t = f.n; t[5] = f.n[f.pos];//交换 t[f.pos] = f.n[5]; if (f.state % 2 == 0) ts = f.state+1;//访问到最后一个数 else ts = f.state; if (!vis[t[0]][t[1]][t[2]][t[3]][t[4]][t[5]][f.pos][ts]){ q.push((node){f.pos, ts, f.d+1, t}); vis[t[0]][t[1]][t[2]][t[3]][t[4]][t[5]][f.pos][ts] = 1; } //Left t = f.n; if (f.pos > 0 && !vis[t[0]][t[1]][t[2]][t[3]][t[4]][t[5]][f.pos-1][f.state]){ q.push((node){f.pos-1, f.state, f.d+1, f.n}); vis[t[0]][t[1]][t[2]][t[3]][t[4]][t[5]][f.pos-1][f.state] = 1; } //Right t = f.n; if (f.state <= 6) ts = f.state+2;//访问到下一个数 else ts = 9; if (f.pos < 5 && !vis[t[0]][t[1]][t[2]][t[3]][t[4]][t[5]][f.pos+1][ts]){ q.push((node){f.pos+1, ts, f.d+1, f.n}); vis[t[0]][t[1]][t[2]][t[3]][t[4]][t[5]][f.pos+1][ts] = 1; } } cout << min; return 0; }