hdu1043八數碼 bfs 打表/雙向bfs/A*+康託判重+逆序奇偶剪枝
寫之前拜讀了這篇文章:八數碼的八境界
個人覺得寫順序為
一(可寫可不寫,介意找工作的的人最好試試這種寫法)-->三 -->二 -->四 -> 六-->八
境界一、逆向廣搜+STL
多組輸入輸出,可以想到打表,bfs時間複雜度為9!,查詢複雜度為O(1)
判重方法:
set<node>vis;
set紅黑樹實現,查詢效率log(n);總的效率nlog(n)(10^6),肯定會TLE
#include <iostream> #include <cstdio> #include <vector> #include <set> #include <map> #include <string> #include <queue> using namespace std; struct node{ public: node(string s, string pa, int p):sty(s),path(pa),pos(p){} public: string sty; string path; int pos; }; map<string,string>res; set<string>vis; int dx[]={-1,1,0,0}; int dy[]={0,0,-1,1}; string dir("durl");//ÄæÏòËÑË÷ bool check(int x,int y) { if(x<0||x>2||y<0||y>2)return false; else return true; } void bfs(){ queue<node>q; node n("12345678x","",8); vis.insert("12345678x"); q.push(n); while(!q.empty()){ n=q.front(); q.pop(); int x=n.pos/3; int y=n.pos%3; for(int i=0;i<4;++i){ int newx=x+dx[i]; int newy=y+dy[i]; if(!check(newx,newy))continue; int newpos=newx*3+newy; swap(n.sty[n.pos],n.sty[newpos]); if(vis.find(n.sty)!=vis.end()){ swap(n.sty[n.pos],n.sty[newpos]); continue; } else{ q.push(node(n.sty,dir[i]+n.path,newpos)); vis.insert(n.sty); res[n.sty]=dir[i]+n.path; swap(n.sty[n.pos],n.sty[newpos]); } } } } int main() { //freopen("in.txt","r",stdin); string in; string tmp; int spos; res[in]=""; bfs(); while(cin>>tmp){ in.push_back(tmp[0]); for(int i=1;i<9;++i){ cin>>tmp; in.push_back(tmp[0]); } //cout<<in<<endl; if(res[in]=="")printf("unsolvable\n"); else cout<<res[in]<<endl; } return 0; }
這份程式碼由於將path放在node裡面,也會MLE
境界三、逆向廣搜+雜湊+打表
是對境界一的改進,set判重改進為cantor判重
從目標狀態123456780反向搜尋,記錄所有可達狀態的路徑
用了兩種記錄路徑的方法,一種是用char path[maxn][36],每個節點維護一個len變數;第二種是每個狀態記錄上一個狀態parent,
path[cur.status].from=parent.stauts
上面是第二種方法,下面是第一種方法程式碼如下
//char path[maxn][42] #include <iostream> #include <cstdio> #include <memory.h> #include <queue> #include <string> #include <cstring> using namespace std; const int maxn = 362880 + 5; int fac[9]; char path[maxn][42]; int vis[maxn]; int dx[] = { -1, 1, 0, 0 }; int dy[] = { 0, 0, -1, 1 }; char dir[]="durl"; struct node { public: node(int p, int s, int l) :pos(p), status(s), len(l){} public: int pos; int status; int len; }; void calFac(int *f, int n) { f[0] = 1; for (int i = 1; i<n; ++i)f[i] = f[i - 1] * i; } int encodeCantor(int *s) { int i, j, num, temp; num = 0; for (i = 0; i<9; ++i){ temp = 0; for (j = i + 1; j<9; ++j){ if (s[j]<s[i]) temp++; } num += fac[9 - 1 - i] * temp; } return num; } void decodeCantor(int *s, int val) { bool flag[10]; memset(flag, 0, sizeof(flag)); for (int i = 0; i<9; ++i){ int _rank = val / fac[8 - i]; for (int j = 0; j <= _rank; ++j){ if (flag[j]){ _rank++; } } s[i] = _rank; flag[_rank] = true;; val = val%fac[8 - i]; } } bool check(int x, int y) { if (x<0 || y<0 || x>2 || y>2)return false; else return true; } void bfs() { queue<node>q; int s[] = { 1, 2, 3, 4, 5, 6, 7, 8, 0 }; node n(8, encodeCantor(s),0); vis[n.status] = 1; path[n.status][0] = '\0'; q.push(n); while (!q.empty()){ n = q.front(); q.pop(); int x = n.pos / 3; int y = n.pos % 3; for (int i = 0; i<4; ++i){ int newx = x + dx[i]; int newy = y + dy[i]; if (!check(newx, newy))continue; int newpos = newx * 3 + newy; decodeCantor(s, n.status); swap(s[n.pos], s[newpos]); int nstatus = encodeCantor(s); if (!vis[nstatus]){ for (int i = 0; i < n.len; i++)path[nstatus][i] = path[n.status][i]; path[nstatus][n.len] = dir[i]; path[nstatus][n.len+1] = '\0'; vis[nstatus] = 1; q.push(node(newpos, nstatus,n.len+1)); } swap(s[n.pos], s[newpos]); } } } void init() { calFac(fac, 9); memset(vis, 0, sizeof(vis)); //cout<<fac[8]*9<<endl; } int main() { //freopen("in.txt", "r", stdin); init(); bfs(); string tmp; int in[9]; while (cin >> tmp){ if (tmp[0] == 'x')in[0] = 0; else in[0] = tmp[0] - '0'; for (int i = 1; i<9; ++i){ cin >> tmp; if (tmp[0] == 'x')in[i] = 0; else in[i] = tmp[0] - '0'; } int status = encodeCantor(in); if (!vis[status])cout << "unsolvable" << endl; else { int len = strlen(path[status]); for (int i = len - 1; i >= 0; --i)printf("%c", path[status][i]); printf("\n"); } } return 0; }
第二種記錄路徑的方法,速度更快,記憶體更小
//記錄上一個stauts #include <iostream> #include <cstdio> #include <memory.h> #include <queue> #include <string> #include <cstring> using namespace std; const int maxn = 362880 + 5; int fac[9]; int vis[maxn]; int dx[] = { -1, 1, 0, 0 }; int dy[] = { 0, 0, -1, 1 }; char dir[]="durl"; struct node { public: node(int p, int s) :pos(p), status(s){} public: int pos; int status; }; struct path { public: int from, dir; }p[maxn]; void calFac(int *f, int n) { f[0] = 1; for (int i = 1; i<n; ++i)f[i] = f[i - 1] * i; } int encodeCantor(int *s) { int i, j, num, temp; num = 0; for (i = 0; i<9; ++i){ temp = 0; for (j = i + 1; j<9; ++j){ if (s[j]<s[i]) temp++; } num += fac[9 - 1 - i] * temp; } return num; } void decodeCantor(int *s, int val) { bool flag[10]; memset(flag, 0, sizeof(flag)); for (int i = 0; i<9; ++i){ int _rank = val / fac[8 - i]; for (int j = 0; j <= _rank; ++j){ if (flag[j]){ _rank++; } } s[i] = _rank; flag[_rank] = true;; val = val%fac[8 - i]; } } bool check(int x, int y) { if (x<0 || y<0 || x>2 || y>2)return false; else return true; } void bfs() { queue<node>q; int s[] = { 1, 2, 3, 4, 5, 6, 7, 8, 0 }; node n(8, encodeCantor(s)); vis[n.status] = 1; p[n.status].from = -1; q.push(n); while (!q.empty()){ n = q.front(); q.pop(); int x = n.pos / 3; int y = n.pos % 3; for (int i = 0; i<4; ++i){ int newx = x + dx[i]; int newy = y + dy[i]; if (!check(newx, newy))continue; int newpos = newx * 3 + newy; decodeCantor(s, n.status); swap(s[n.pos], s[newpos]); int nstatus = encodeCantor(s); if (!vis[nstatus]){ p[nstatus].from = n.status; p[nstatus].dir = i; vis[nstatus] = 1; q.push(node(newpos, nstatus)); } swap(s[n.pos], s[newpos]); } } } void print(int s) { while (p[s].from != -1) { printf("%c", dir[p[s].dir]); s = p[s].from; } printf("\n"); } void init() { calFac(fac, 9); memset(vis, 0, sizeof(vis)); } int main() { //freopen("in.txt", "r", stdin); init(); bfs(); string tmp; int in[9]; while (cin >> tmp){ if (tmp[0] == 'x')in[0] = 0; else in[0] = tmp[0] - '0'; for (int i = 1; i<9; ++i){ cin >> tmp; if (tmp[0] == 'x')in[i] = 0; else in[i] = tmp[0] - '0'; } int status = encodeCantor(in); if (!vis[status])cout << "unsolvable" << endl; else { print(status); } } return 0; }
境界四、雙向BFS+康託判重+剪枝
如圖,雙向bfs可以節約一半的時間和空間,注意境界一複雜度時9!,現在是9!/2,還不夠快。
故注意進行奇偶剪枝,否則會TLE
剪枝原理:
逆序數:對於n個不同的元素,先規定各元素之間有一個標準次序(例如n個 不同的自然數,可規定從小到大為標準次序),於是在這n個元素的任一排列中,當某兩個元素的先後次序與標準次序不同時,就說有1個逆序。逆序對的總數稱為逆序數
只要終止狀態和起始狀態的逆序數(空的位置不算)奇偶性不同,就一定不能達到目標狀態。
分析:向左或者向右移動,逆序數的奇偶行不變....0,xt,xt+1...,將.0和xt交換,奇偶性是不變的
對 x1 x2 x3
x4 x5 x6
x7 0 x8
將0和x5交換,x1 x2 x3 x4 x5 x6 x7 0 x8,下面分三種情況
a)若 x5>x6 && x5> x7,則逆序數+2
a)若 x5 <x6 && x5<x7,則逆序數-2
a)若 x5 在6 和x7之間,則逆序數不變
通過以上分析可知:只有起始狀態可終止狀態逆序數奇偶性相同才能轉換
雙向bfs,採用兩個佇列q1和q2,一個從起始狀態向目標狀態擴充套件,另一個從目標狀態像起始狀態擴充套件
判別重可以採用
int vis[manx];//q1為1,q2為2
//可以用
bool vis1[maxn],vis2[maxn];
輸出路徑時
q1的另用一個數組記錄下來
char tmp[36]; int len = 0;
while (p1[s]!= -1){
tmp[len++] = dir1[d1[s]];
s = p1[s];
}
q2利用和境界三一樣的方法
程式碼如下
#include <stdio.h>
#include <queue>
#include <memory.h>
using namespace std;
const int maxn = 362880 + 5;
char *dir1 = "udlr";
char *dir2 = "durl";
int dx[] = { -1, 1, 0, 0 };
int dy[] = { 0, 0, -1, 1 };
struct node
{
public:
int status, pos;
};
int p1[maxn], p2[maxn];
int d1[maxn], d2[maxn];
bool vis1[maxn],vis2[maxn];
int fac[9];
void init()
{
fac[0] = 1;
for (int i = 1; i<9; ++i){
fac[i] = i*fac[i - 1];
}
}
int encodeCantor(int *s)
{
int _rank, sum = 0;
for (int i = 0; i < 9; ++i){
_rank = 0;
for (int j = i + 1; j<9; ++j){
if (s[i]>s[j])_rank++;
}
sum += fac[8 - i] * _rank;
}
return sum;
}
void decodeCantor(int *arr, int s)
{
bool flag[9];
memset(flag, 0, sizeof(flag));
for (int i = 0; i<9; ++i){
int _rank = s / fac[8 - i];
for (int j = 0; j <= _rank; ++j){
if (flag[j])_rank++;
}
arr[i] = _rank;
flag[_rank] = 1;
s = s%fac[8 - i];
}
}
bool check(int x, int y)
{
if (x<0 || y<0 || x>2 || y>2)return false;
else return true;
}
void print(int status)
{
int s = status;
char tmp[36]; int len = 0;
while (p1[s]!= -1){
tmp[len++] = dir1[d1[s]];
s = p1[s];
}
s = status;
for (int i = len - 1; i >= 0; i--)printf("%c", tmp[i]);
while (p2[s] != -1){
printf("%c", dir2[d2[s]]);
s = p2[s];
}
printf("\n");
}
void bfs(int init_pos, int init_status)
{
queue<node>q1, q2;
memset(vis1, 0, sizeof(vis1));
memset(vis2, 0, sizeof(vis2));
int arr[9];
int aim[] = { 1, 2, 3, 4, 5, 6, 7, 8, 0 };
int aim_s = encodeCantor(aim);
node n;
n.status=init_status;
n.pos=init_pos;
q1.push(n);
n.status=aim_s;
n.pos=8;
q2.push(n);
node cur;
node next;
p1[init_status] = -1;
p2[aim_s] = -1;
vis1[init_status] = 1;
vis2[aim_s] = 1;
int flag;
while (!q1.empty() || !q2.empty()){
if (!q1.empty() && (q2.empty() || q1.size() <= q2.size())) {//選擇較少的擴充套件,效率較高
flag = 1;
cur = q1.front();
q1.pop();
if (vis2[cur.status]){
print(cur.status);
return;
}
}
else {
flag = 2;
cur = q2.front();
q2.pop();
if (vis1[cur.status]){
print(cur.status);
return;
}
}
decodeCantor(arr, cur.status);
int x = cur.pos / 3; int y = cur.pos % 3;
for (int i = 0; i<4; ++i){
int nx = x + dx[i]; int ny = y + dy[i];
if (!check(nx, ny))continue;
int newpos = nx * 3 + ny;
swap(arr[cur.pos], arr[newpos]);
int nstatus = encodeCantor(arr);
if (flag == 1 && !vis1[nstatus]){
p1[nstatus] = cur.status;
d1[nstatus] = i;
if (vis2[nstatus]){
print(nstatus);
return;
}
else {
vis1[nstatus] = 1;
next.status=nstatus;
next.pos=newpos;
q1.push(next);
}
}
else if (flag == 2 && !vis2[nstatus]){
p2[nstatus]= cur.status;
d2[nstatus] = i;
if (vis1[nstatus]){
print(nstatus);
return;
}
else{
vis2[nstatus] = 1;
next.status=nstatus;
next.pos=newpos;
q2.push(next);
}
}
swap(arr[cur.pos], arr[newpos]);
}
}
return;
}
//奇偶剪枝
bool pruning(int *arr){
int flag = 0;
for (int i = 0; i<9; ++i){
if (arr[i] == 0) continue;
for (int j = i + 1; j<9; ++j){
if (arr[j] && arr[i]>arr[j]) flag++;
}
}
if (flag % 2) return true;
return false;
}
int main()
{
//freopen("in.txt", "r", stdin);
char tmp[3];
int in[9];
int pos;
init();
while (scanf("%s", tmp) != EOF){
if (tmp[0] == 'x'){
in[0] = 0;
pos = 0;
}
else in[0] = tmp[0] - '0';
for (int i = 1; i<9; ++i){
scanf("%s", tmp);
if (tmp[0] == 'x'){
in[i] = 0;
pos = i;
}
else in[i] = tmp[0] - '0';
}
int status = encodeCantor(in);
if (pruning(in))printf("unsolvable\n");
else {
bfs(pos, status);
}
}
return 0;
}
境界六、A*+cantor判重+曼哈頓距離
境界五和境界六差不多,就是啟發式函式使用的不一樣,直接寫了境界六
啟發式演算法的估價函式為 f(n) = g(n) + h(n)
G 表示從起點 A 移動到網格上指定方格的移動耗費 (可沿斜方向移動).
H 表示從指定的方格移動到終點 B 的預計耗費 (H 有很多計算方法, 這裡我們設定只可以上下左右移動).
A*演算法的估價函式可以表示為
f'(n) = g'(n) + h'(n)
f’(n)是估價函式,g’(n)是起點到終點的最短路徑值,h’(n)是n到目標的最斷路經的啟發值。由 於這個f’(n)其實是無法預先知道的,所以我們用估價函式f(n)做近似。g(n)代替g’(n),但 g(n)>=g’(n) 才可(大多數情況下都是滿足的,可以不用考慮),h(n)代替h’(n),但h(n)<=h’(n)才可(這一點特別的重 要)。
這裡的G指的是bfs擴充套件的層數,因為一層就是一步
H指的是當前位置到終點的曼哈頓距離
計算曼哈頓距離的函式為
int getH(int *arr)
{
int x, y;
int h = 0;
for (int i = 0; i<9; ++i){
if (arr[i]){
x = i / 3;
y = i % 3;
h += abs(x - tx[arr[i]]) + abs(y - ty[arr[i]]);//tx,ty分別表示arr[i]的目標位置座標
}
}
return h;
}
上程式碼
#include <iostream>
#include <stdio.h>
#include <queue>
#include <memory.h>
#include <stdlib.h>
using namespace std;
const int maxn = 362880 + 5;
int fac[] = { 1, 1, 2, 6, 24, 120, 720, 5040, 40320 };
char *dir = "udlr";
int dx[] = { -1, 1, 0, 0 };
int dy[] = { 0, 0, -1, 1 };
bool vis[maxn];
struct node
{
int status, pos;
int g, h;
bool operator<(const node&n)const{
return (g + h)>(n.g + n.h);
}
};
struct path
{
int from, dir;
}p[maxn];
int tx[] = { 2, 0, 0, 0, 1, 1, 1, 2, 2 };
int ty[] = { 2, 0, 1, 2, 0, 1, 2, 0, 1 };
int encodeCantor(int *arr)
{
int sum = 0;
for (int i = 0; i<9; ++i){
int _rank = 0;
for (int j = i + 1; j<9; ++j){
if (arr[i]>arr[j])_rank++;
}
sum += _rank*fac[8 - i];
}
return sum;
}
void decodeCantor(int *arr, int val)
{
int flag[9], _rank;
memset(flag, 0, sizeof(flag));
for (int i = 0; i<9; ++i){
_rank = val / fac[8 - i];
for (int j = 0; j <= _rank; ++j){
if (flag[j])_rank++;
}
arr[i] = _rank;
flag[_rank] = 1;
val = val%fac[8 - i];
}
}
int getH(int *arr)
{
int x, y;
int h = 0;
for (int i = 0; i<9; ++i){
if (arr[i]){
x = i / 3;
y = i % 3;
h += abs(x - tx[arr[i]]) + abs(y - ty[arr[i]]);
}
}
return h;
}
bool pruning(int *arr)
{
int sum = 0;
for (int i = 0; i<9; ++i){
if (!arr[i])continue;
for (int j = i + 1; j<9; ++j){
if (arr[j]&&arr[i]>arr[j])sum++;
}
}
if (sum % 2)return true;
else return false;
}
bool check(int x, int y)
{
if (x<0 || y<0 || x>2 || y>2)return false;
else return true;
}
void A_star(int *arr)
{
int aim[] = { 1, 2, 3, 4, 5, 6, 7, 8, 0 };
int aim_s = encodeCantor(aim);
priority_queue<node>q;
memset(vis, 0, sizeof(vis));
node cur, next;
int status = encodeCantor(arr);
for (int i = 0; i<9; ++i){
if (!arr[i]){
cur.pos = i;
break;
}
}
cur.status = status;
cur.g = 0;
cur.h = getH(arr);
q.push(cur);
p[status].from = -1;
vis[status] = 1;
while (!q.empty()){
cur = q.top();
q.pop();
decodeCantor(arr, cur.status);
if (cur.status == aim_s){
int s = cur.status, len = 0;
char res[maxn];
while (p[s].from != -1){
res[len++] = dir[p[s].dir];
s = p[s].from;
}
for (int i = len - 1; i >= 0; i--){
printf("%c", res[i]);
}
printf("\n");
return;
}
else{
int x = cur.pos / 3; int y = cur.pos % 3;
for (int i = 0; i<4; ++i){
int nx = x + dx[i];
int ny = y + dy[i];
if (!check(nx, ny))continue;
int newpos = nx * 3 + ny;
swap(arr[newpos], arr[cur.pos]);
int nstatus = encodeCantor(arr);
if (!vis[nstatus]){
next.status = nstatus;
next.pos = newpos;
next.g = cur.g + 1;
next.h = getH(arr);
p[next.status].from = cur.status;
p[next.status].dir = i;
vis[next.status] = 1;
q.push(next);
}
swap(arr[newpos], arr[cur.pos]);
}
}
}
printf("unsolvable\n");
}
int main()
{
//freopen("in.txt", "r", stdin);
char tmp[5];
int in[9];
while (scanf("%s", tmp) != EOF){
if (tmp[0] == 'x')in[0] = 0;
else in[0] = tmp[0] - '0';
for (int i = 1; i<9; ++i){
scanf("%s", tmp);
if (tmp[0] == 'x')in[i] = 0;
else in[i] = tmp[0] - '0';
}
//int status=encodeCantor(in);
if (pruning(in))printf("unsolvable\n");
else A_star(in);
}
return 0;
}
相關推薦
hdu1043八數碼 bfs 打表/雙向bfs/A*+康託判重+逆序奇偶剪枝
寫之前拜讀了這篇文章:八數碼的八境界 個人覺得寫順序為 一(可寫可不寫,介意找工作的的人最好試試這種寫法)-->三 -->二 -->四 -> 六-->八 境界一、逆向廣搜+STL 多組輸入輸出,可以想到打表,bfs時間複雜度為9!,查詢複雜度
hdu1043 Eight(A*/雙向BFS/單項BFS打表+康託展開)
題意描述:經典八數碼問題,給定八數碼的初始序列,求經過u、r、l、d四種操作到達1 2 3 4 5 6 7 8 x的狀態,打印出操作序列? 解題思路:A*/雙向BFS/單項BFS打表+康託展開 202msAC 方法一:BFS逆向打表+康託展開:從1 2 3 4 5
HDU 1043 Eight(反向BFS+打表+康托展開)
front int 二維 -i 轉換成 思路 離散化 strlen acm 題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=1043 題目大意:傳統八數碼問題 解題思路:就是從“12345678x”這
hdu 6253 (bfs打表)
連結:http://acm.hdu.edu.cn/showproblem.php?pid=6253 題意: 馬可以往一個方向走兩步,然後轉個彎走一步,這樣算一次動作,求問馬n次動作後,能到達多少個點,重複到達的點只算一次。 思路: 一開始完全沒思路,畫圖找了半天把自己畫崩了,後面看到資料和樣例感覺這應
poj 1077 Eight (八數碼問題——A*+cantor展開+奇偶剪枝)
www. += 優先級 pri 排列 view 組成 esp 改變 題目來源: http://poj.org/problem?id=1077 題目大意: 給你一個由1到8和x組成的3*3矩陣,x每次可以上下左右四個方向交換。求一條路徑,得到12345678x這樣的矩陣。
HDU_1043 Eight 【逆向BFS + 康託展開 】【A* + 康託展開 】
一、題目 http://acm.hdu.edu.cn/showproblem.php?pid=1043 二、兩種方法 該題很明顯,是一個八數碼的問題,就是9宮格,裡面有一個空格,外加1~8的數字,任意一種情況,如果能通過移動空格使數碼組成 1 2 3 4 5 6 7 8 0 的形式,就輸
HDU1097暴力打表找規律a^b
A hard puzzle Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Oth
HDU1043 Eight A +康託
The 15-puzzle has been around for over 100 years; even if you don't know it by that name, you've seen it. It is constructed with 15 sliding tiles, each wit
HDU 1043 Eight八數碼解題思路(bfs+hash 打表 IDA* 等)
中間 節點 sca 技巧 length div clu 鏈接 output 題目鏈接 https://vjudge.net/problem/HDU-1043 經典的八數碼問題,學過算法的老哥都會拿它練搜索 題意: 給出每行一組的數據,每組數據代表3*3的八數碼表,要求程序復
【 HDU1043-經典BFS+康拓展開 八數碼】 (待更)
給定一個序列,由1~8數字和字母x組成,表示的是一個3*3的矩形。每次操作x都能與相鄰的數字交換,問如何操作才能使得序列為{1,2,3,4,5,6,7,8,x}。 //多組資料-需要計算全部路徑後直接輸出 //反向搜尋+打表(離線) #include<iostream&
【基礎練習】【BFS+A*】codevs1225八數碼難題題解
一點 說明 優先 data- push 練習 bool csdn tarjan 題目描寫敘述 Description Yours和zero在研究A*啟示式算法.拿到一道經典的A*問題,可是他們不會做,請你幫他們. 問題描寫敘述 在3×3的棋
八數碼問題--bfs
mes als bsp lin dir str2 amt i++ pac 1 #include<iostream> 2 #include<cstring> 3 #define max 1000000 4 using namespace st
bzoj 1098 [POI2007]辦公樓biu bfs+補圖+雙向鏈表
solved 必須 ++ ont 一行 ast color cst code [POI2007]辦公樓biu Time Limit: 20 Sec Memory Limit: 162 MBSubmit: 1543 Solved: 743[Submit][Statu
Prime Path (打表+BFS) POJ-3126
The ministers of the cabinet were quite upset by the message from the Chief of Security stating that they would all have to change the four-digit
Eight HDU - 1043 八數碼問題 康託展開 + 反向 bfs +記錄路徑
bfs 剪枝要點 visit陣列 hash函式(康託展開) 記憶化 bfs 打表儲存所有可達路徑 優先佇列 periority queue 多點同時bfs 反向bfs + bfs 打表儲存所有路徑 stl + 正向bfs
哈爾濱理工大學軟體與微電子學院第八屆程式設計競賽同步賽(高年級) G 小樂樂打遊戲 【BFS】
傳送門:https://ac.nowcoder.com/acm/contest/301/G 題意概括: 給一個地圖,有一個火山口 F 一個 起點 S 一個出口 E。 連結:https://ac.nowcoder.com/acm/contest/301/G來源:牛客網  
hdu1043 雙向bfs+康拓展開【經典】
題意大致就是給你一個3X3的矩陣,你要把矩陣轉換成12345678的形式,在矩陣中是有一個空缺處可以供你移動滑塊的,問你是否可以把給你的矩陣轉換成12345678的形式,算了題意自己去看吧,有圖更加直接 思路:這裡主要考慮這幾個方面:第一個如何判斷經過一定轉換的矩陣是規範矩陣?這裡就用到了康
*【牛客 - 301哈爾濱理工大學軟體與微電子學院第八屆程式設計競賽同步賽(高年級)】小樂樂打遊戲(bfs,雙元bfs,思維)
題幹: 小樂樂覺得學習太簡單了,剩下那麼多的時間好無聊,於是便想打遊戲。 最近新出了一個特別火的遊戲,叫吃豬,小樂樂準備玩一玩。 吃豬遊戲很簡單,給定一個地圖,大小為
2612 bfs加打表
打表預處理會降低複雜度,如果每次找一個'@'都跑一次bfs的話會超時; #include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #
哈理工第八屆程式設計競賽同步賽(高年級) G-小樂樂打遊戲 (bfs,挑題的後果)
題目連結:哆啦A夢傳送門 剛看到這道題,一看是走迷宮類的題,看到就沒興趣,最不喜歡做的就是這些用bfs,dfs做的題,所以很顯然比賽時我想都不想,想著不要這題也罷,賽後才知道這題是有多水,嘔吐,從這次總結了一次教訓,以後打比賽,不要挑題做,不然會很吃虧,還是好好敲遍bfs好了,當練手了,最不