hdu1043:
poj1077:
題意:眾所周知的八數碼問題,就不再描述了。不得不說,為了練習a*以及ida*就直接看題解了。 了解之後分析如下。
解題報告:
先談a*。a*是一種
啟發式搜尋,也就是說在每次搜尋前,先進行在狀態空間中對每乙個搜尋的位置通過f(n) = g(n) + h(n)進行評估,得到最好的位置,再從這個位置,
進行搜尋直到目標。其中f(n)是從初始點經由節點n到目標點的估價函式,g(n) 是在狀態空間中從初始節點到n節點的實際代價,h(n)是從n到目標節點最佳路徑的估計代價。
然後是ida*。a*演算法和迭代加深演算法的結合。
1.搜尋框架?a*(ida*)演算法。搜尋直到終態結束,或該狀態非法進行下一狀態。
2.狀態?直接記錄每個狀態的maze、x位置資訊以及a*所需f、g、h。同時使用hash值指向所有狀態。
3.狀態轉移?x與上下左右互換,更新狀態資訊。
4.剪枝?乙個簡單有效的剪枝逆序數為奇則必定無解。
5.hash以及h?
hash可通過各位置逆序數乘位置雜湊值之和雜湊。h為所有數字塊的曼哈頓距離和。
具體而言。a*通過構造優先佇列
實現搜尋。
構造優先佇列時當f相同時按照g值從大到小排序,這樣又是乙個很給力的減枝。
#include #include #include #include using namespace std;
//a*: 因為每次移動都會影響乙個點的曼哈頓距離(不算x)
//構造h()為所有數字塊的曼哈頓距離和,用逆序數hash(算x)
//根據逆序數奇偶性(不算x)減掉無法到達的情況,
struct node
node(const node & rhs)
//估價函式小的先出隊,相同則實際代價大的先出隊
friend bool operator < (const node & a, const node & b)
}st;
const int dir[4][2] = ,,, };//方向
char dr[5] = "drul"; //方向查詢表
int pos[9][2] = ; //位置資訊
int fac[9] = ; //hash雜湊因子
char path[370000];
bool vis[370000];
int pre[370000];
int shash;
int h(const node s) //估價函式,偏移步數
return ans;
}int hash_node(const node s) //hash雜湊,儲存狀態
return ans;
}bool check_h() //逆序為奇返回true
} return cnt & 1;
}bool bfs()
} return false;
}void print(int h)
}char in[100];
int main()
if (check_h())
st.g = 0; st.h = h(st); st.f = st.h;
if ((shash = hash_node(st)) == 0)
int thash = bfs();
print(0); //遞迴輸出答案
puts("");
} return 0;
}
而ida*的話,和a*相同的h()函式。
當前h深度下一層一層地進行搜尋
。
#include #include using namespace std;
struct node
node(const node & rhs)
}ts, s;
const int maxn = 370000;
const int dir[4][2] = ,,, };
const char dr[5] = "drul";
const int fac[9] = ;
const int pos[2] = ;
char path[maxn];
bool vis[maxn];
int deep;
int h(const node st)
return ans;
}int mhash(const node st)
return ans;
}bool check()
} return cnt & 1;
}int dfs(int d)
vis[ihv] = true;
ts.r = nr, ts.c = nc;
path[d] = dr[dd];
if (dfs(d + 1)) return true;
vis[ihv] = false;
ts.r = r, ts.c = c;
ts.maze[nr][nc] = ts.maze[r][c];
ts.maze[r][c] = 'x';
} return false;
}int main()
if (check())
memset(vis, false, sizeof(vis));
vis[mhash(s)] = true;
ts = s; deep = 0;
while (true)
for (int i = 0; i < deep; i++)
putchar(path[i]);
puts("");
} return 0;
}
最後打卡一下。之前ubuntu的ibus預設的中文輸入法雙拼的,當時就感覺是一堆亂碼,玩毛。不幾天前,嘗試用雙拼了。
八數碼(IDA 演算法)
八數碼 ida 就是迭代加深和a 估價的結合 在迭代加深的過程中,用估計函式剪枝優化 並以比較優秀的順序進行擴充套件,保證最早搜到最優解 需要空間比較小,有時跑得比a 還要快 include include include include include using namespace std in...
A 搜尋演算法,poj1077 八數碼
今天看了a 搜尋演算法,聽說牛逼的很,不過關鍵還是在於它的評估函式,估計也不一定每題都能這麼容易想吧 就 來說吧,s,儲存所有所搜到的結點的資訊,包括空格位置,深度及評估值,這裡不給出h是因為h一直在變,b儲存開始結點資訊,visited儲存是否訪問到,接下來方向,答案,heap是為了提速而寫的堆實...
八數碼問題的A 演算法求解
a 演算法是啟發式搜素演算法中較為出名和高效的演算法之一,其關鍵是對於啟發式函式的實際,啟發式函式h x 需要盡可能的接近實際的h x h x 下面是人工智慧八數碼問題使用a 演算法求解的原始碼放在部落格上記錄一下。程式使用放錯位置的棋子的個數作為啟發式函式。include include incl...