给定一个由连续整数组成的序列(长度1-9),问最少需要多少次剪切粘贴操作能变成1-n的连续序列
书中给的点拨非常重要:
1、启发函数的选择
2、迭代加深的应用
3、依据“每次剪切粘贴最多只能改变三个数字的位置正确性”来剪枝
另外有几个地方有疑惑:
1、剪切粘贴的操作,我尝试用memcpy替代中间数组,速度却更慢了
2、尝试用memcmp来判断到达目标,没有成功
3、如果不用map来做距离数组,如何用其他方法做呢?
Run Time: 3.219s
#include<cstring> #include<cstdlib> #include<cstdio> #include<vector> #include<map> #include<queue> using namespace std; //Global Variables. int kase = 1, n, maxd = 9; vector<int> seq; map<vector<int>,int> vis; ///// int h(const vector<int>& a) { //Heuristic Func int cnt = 0; for(int i = 1; i < a.size(); i ++) if(a[i] != a[i-1] + 1) cnt ++; return cnt; } struct State { vector<int> seq; int d, h; bool operator < (const State& s) const { return d + h > s.d + s.h; //A* algorithm } }; int solve() { priority_queue<State> q; State startS; startS.seq = seq; startS.d = 0; startS.h = h(startS.seq); q.push(startS); while(!q.empty()) { State u = q.top(); q.pop(); if(vis.count(u.seq)) { if(vis[u.seq] > u.d) vis[u.seq] = u.d; else continue; } else vis[u.seq] = u.d; int flag = 1; for(int i = 0; i < n; i ++) if(u.seq[i] != (i+1)) { flag = 0; break; } //Compare with target if(flag) { //arrival. printf("Case %d: %d\n", kase ++, u.d); //print ans return 1; } if(u.d > maxd) continue; //Iterative Deepening if(3*u.d + h(u.seq) > 3*maxd) continue; //Pruning for(int a = 0; a < n; a ++) { for(int b = a; b < n; b ++) { //cut start & end position for(int c = 0; c <= n; c ++) { //paste position vector<int> v = u.seq; vector<int> tmp; if(c < a) { for(int i = a; i <= b; i ++) tmp.push_back(v[i]); for(int i = c; i < a; i ++) tmp.push_back(v[i]); for(int i = c; i <= b; i ++) v[i] = tmp[i-c]; } else if(c > b) { for(int i = b+1; i < c; i ++) tmp.push_back(v[i]); for(int i = a; i <= b; i ++) tmp.push_back(v[i]); for(int i = a; i < c; i ++) v[i] = tmp[i-a]; } else continue; //invalid operation. State newS; newS.seq = v; newS.d = u.d + 1; newS.h = h(newS.seq); q.push(newS); } } } } return 0; } int main() { while(scanf("%d", &n) && n) { seq.resize(n); for(int i = 0; i < n; i ++) scanf("%d", &seq[i]); for(maxd = 1; maxd <= 9; maxd ++) { //Iterative Deepening vis.clear(); if(solve()) break; } } return 0; }