POJ2308连连看dfs+bfs+优化
生活随笔
收集整理的這篇文章主要介紹了
POJ2308连连看dfs+bfs+优化
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
DFS+BFS+MAP+剪枝
題意:
? ? ? 就是給你一個(gè)10*10的連連看狀態(tài),然后問你最后能不能全部消沒?
思路:
? ? ?首先要明確這是一個(gè)搜索題目,還有就是關(guān)鍵的一點(diǎn)就是連連看這個(gè)游戲是存在決策的,就是如果當(dāng)前的這個(gè)點(diǎn)可以連接好幾個(gè)點(diǎn)的話,我們選擇那個(gè)點(diǎn)連接是不一樣的,所以還要遍歷所有的可能連接點(diǎn),這樣考慮的話單純的一個(gè)搜索肯定不行了,可以用一個(gè)深搜套廣搜的的結(jié)構(gòu),深搜是為了遍歷順序,廣搜所為了得到當(dāng)前點(diǎn)可以消去那些點(diǎn)(必要一個(gè)一個(gè)搜,要直接把所有的可能都搜出來,就是把杭電的那個(gè)bfs擴(kuò)展下),但是直接暴力時(shí)間復(fù)雜度肯定接受不了,目測是,目測是多少我也不知道,但是存在這樣的數(shù)據(jù)t = O(100^25),所以要優(yōu)化,關(guān)鍵是在優(yōu)化,下面是我能想到的幾個(gè)優(yōu)化
(1)首先把所有的卡片都單獨(dú)拿出來,放到一個(gè)結(jié)構(gòu)體里面,這樣每次遍歷的時(shí)候直接就只遍歷數(shù)組,不用遍歷所有的圖。
(2)直接判斷每種卡片出現(xiàn)的次數(shù)的奇偶。
(3)還有就是開一個(gè)狀態(tài)記錄當(dāng)前的這個(gè)狀態(tài)是否出現(xiàn)過,這個(gè)我是用的map進(jìn)行hash的,這個(gè)優(yōu)化有種記憶化搜索的感覺。
(4)還有最后一個(gè)(百度的),也是最關(guān)鍵的,如果有兩種卡片都只剩下兩個(gè)了,并且出現(xiàn)這樣的姿勢
AB
BA
? ?顯然這樣是連接不了的,這樣感覺不會優(yōu)化多少,但是在這個(gè)題目里,這樣貌似優(yōu)化很大,原因我感覺是在卡片的種類上的原因,卡片種類只有4種,這個(gè)也只是猜測,其實(shí)我力推的優(yōu)化是(2,3)可惜沒有4一直超時(shí)。
還有就是一定要明確,連連看是存在決策問題的。
#include<map>
#include<queue>
#include<stdio.h>
#include<string.h>
#include<string>
using namespace std;
typedef struct
{
? ? int x ,y ,t;
}NODE;
typedef struct
{
? ? int x ,y;
}CARD;
NODE xin ,tou;
CARD card[105];
CARD can[105];
int ss[5];
int cans ,mkans ,n ,m ,nowc ,cards;
int _map[12][12];
int dir[4][2] = {0 ,1 ,0 ,-1 ,1 ,0 ,-1 ,0};
map<string ,int>MARK;
bool ok(int x ,int y)
{
? ? return x >= 1 && x <= n && y >= 1 && y <= m && (!_map[x][y] || _map[x][y] == nowc);
}
bool jude()
{
? ? char str[105];
? ? for(int i = 1 ;i <= cards ;i ++)
? ? if(_map[card[i].x][card[i].y]) str[i-1] = 'a';
? ? else str[i-1] = 'b';
? ? str[cards] = '\0';
? ? if(MARK[str]) return 0;
? ? MARK[str] = 1;
? ? return 1;
}
int BFS(int x ,int y)
{
? ? int mark[12][12] = {0};
? ? nowc = _map[x][y];
? ? cans = 0;
? ? xin.x = x ,xin.y = y ,xin.t = 0;
? ? queue<NODE>q;
? ? q.push(xin);
? ? while(!q.empty())
? ? {
? ? ? ? tou = q.front();
? ? ? ? q.pop();
? ? ? ? if(_map[tou.x][tou.y] == nowc && !(tou.x == x && tou.y == y))
? ? ? ? {
? ? ? ? ? ? cans ++;
? ? ? ? ? ? can[cans].x = tou.x;
? ? ? ? ? ? can[cans].y = tou.y;
? ? ? ? ? ? continue;
? ? ? ? }
? ? ? ? if(tou.t >= 3) continue;
? ? ? ? for(int i = 0 ;i < 4 ;i ++)
? ? ? ? {
? ? ? ? ? ? xin.x = tou.x ,xin.y = tou.y ,xin.t = tou.t + 1;
? ? ? ? ? ? while(1)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? xin.x += dir[i][0];
? ? ? ? ? ? ? ? xin.y += dir[i][1];
? ? ? ? ? ? ? ? if(!ok(xin.x ,xin.y)) break;
? ? ? ? ? ? ? ? if(!mark[xin.x][xin.y])
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? mark[xin.x][xin.y] = 1;
? ? ? ? ? ? ? ? ? ? q.push(xin);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? }
? ? }
? ? return cans;
}
bool CCC(int a ,int b)
{
? ? for(int i = 1 ;i <= cards ;i ++)
? ? {
? ? ? ? int x = card[i].x ,y = card[i].y;
? ? ? ? if(_map[x][y] == a)
? ? ? ? {
? ? ? ? ? ? if(_map[x+1][y+1] == a && _map[x+1][y] == b && _map[x][y+1] == b)
? ? ? ? ? ? return 1;
? ? ? ? ? ? return 0;
? ? ? ? }
? ? ? ? if(_map[x][y] == b)
? ? ? ? {
? ? ? ? ? ? if(_map[x+1][y+1] == b && _map[x+1][y] == a && _map[x][y+1] == a)
? ? ? ? ? ? return 1;
? ? ? ? ? ? return 0;
? ? ? ? }
? ? }
}
bool CUT()
{
? ? for(int i = 1 ;i <= 4 ;i ++)
? ? for(int j = i + 1 ;j <= 4 ;j ++)
? ? {
? ? ? ? if(ss[i] == ss[j] && ss[i] == 2)
? ? ? ? {
? ? ? ? ? ? if(CCC(i ,j)) return 1;
? ? ? ? }
? ? }
? ? return 0;
}
void DFS(int nows)
{
? ? if(!nows) mkans = 1;
? ? if(mkans) return ;
? ? if(!jude()) return ;
? ? if(CUT()) return ;
? ? for(int i = 1 ;i <= cards ;i ++)
? ? {
? ? ? ? if(mkans) return ;
? ? ? ? int x = card[i].x ,y = card[i].y;
? ? ? ? if(!_map[x][y]) continue;
? ? ? ? BFS(x ,y);
? ? ? ? ss[_map[x][y]] -= 2;
? ? ? ? for(int j = 1 ;j <= cans ;j ++)
? ? ? ? {
? ? ? ? ? ? int tmp = _map[x][y];
? ? ? ? ? ? int xx = can[j].x ,yy = can[j].y;
? ? ? ? ? ? _map[x][y] = _map[xx][yy] = 0;
? ? ? ? ? ? DFS(nows - 2);
? ? ? ? ? ? _map[x][y] = _map[xx][yy] = tmp;
? ? ? ? }
? ? ? ? ss[_map[x][y]] += 2;
? ? }
}
int main ()
{
? ? char str[12];
? ? while(~scanf("%d %d" ,&n ,&m) && n + m)
? ? {
? ? ? ? memset(_map ,0 ,sizeof(_map));
? ? ? ? memset(ss ,0 ,sizeof(ss));
? ? ? ? cards = 0;
? ? ? ? for(int i = 1 ;i <= n ;i ++)
? ? ? ? {
? ? ? ? ? ? scanf("%s" ,str);
? ? ? ? ? ? for(int j = 1 ;j <= m ;j ++)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? if(str[j-1] == '*') _map[i][j] = 0;
? ? ? ? ? ? ? ? else
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? _map[i][j] = str[j-1] - 'A' + 1;
? ? ? ? ? ? ? ? ? ? cards ++;
? ? ? ? ? ? ? ? ? ? card[cards].x = i;
? ? ? ? ? ? ? ? ? ? card[cards].y = j;
? ? ? ? ? ? ? ? ? ? ss[_map[i][j]] ++;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? if(ss[1]%2 || ss[2]%2 || ss[3]%2 || ss[4]%2)
? ? ? ? {
? ? ? ? ? ? printf("no\n");
? ? ? ? ? ? continue;
? ? ? ? }
? ? ? ? mkans = 0;
? ? ? ? MARK.clear();
? ? ? ? DFS(cards);
? ? ? ? mkans ? printf("yes\n"):printf("no\n");
? ? }
? ? return 0;
}
題意:
? ? ? 就是給你一個(gè)10*10的連連看狀態(tài),然后問你最后能不能全部消沒?
思路:
? ? ?首先要明確這是一個(gè)搜索題目,還有就是關(guān)鍵的一點(diǎn)就是連連看這個(gè)游戲是存在決策的,就是如果當(dāng)前的這個(gè)點(diǎn)可以連接好幾個(gè)點(diǎn)的話,我們選擇那個(gè)點(diǎn)連接是不一樣的,所以還要遍歷所有的可能連接點(diǎn),這樣考慮的話單純的一個(gè)搜索肯定不行了,可以用一個(gè)深搜套廣搜的的結(jié)構(gòu),深搜是為了遍歷順序,廣搜所為了得到當(dāng)前點(diǎn)可以消去那些點(diǎn)(必要一個(gè)一個(gè)搜,要直接把所有的可能都搜出來,就是把杭電的那個(gè)bfs擴(kuò)展下),但是直接暴力時(shí)間復(fù)雜度肯定接受不了,目測是,目測是多少我也不知道,但是存在這樣的數(shù)據(jù)t = O(100^25),所以要優(yōu)化,關(guān)鍵是在優(yōu)化,下面是我能想到的幾個(gè)優(yōu)化
(1)首先把所有的卡片都單獨(dú)拿出來,放到一個(gè)結(jié)構(gòu)體里面,這樣每次遍歷的時(shí)候直接就只遍歷數(shù)組,不用遍歷所有的圖。
(2)直接判斷每種卡片出現(xiàn)的次數(shù)的奇偶。
(3)還有就是開一個(gè)狀態(tài)記錄當(dāng)前的這個(gè)狀態(tài)是否出現(xiàn)過,這個(gè)我是用的map進(jìn)行hash的,這個(gè)優(yōu)化有種記憶化搜索的感覺。
(4)還有最后一個(gè)(百度的),也是最關(guān)鍵的,如果有兩種卡片都只剩下兩個(gè)了,并且出現(xiàn)這樣的姿勢
AB
BA
? ?顯然這樣是連接不了的,這樣感覺不會優(yōu)化多少,但是在這個(gè)題目里,這樣貌似優(yōu)化很大,原因我感覺是在卡片的種類上的原因,卡片種類只有4種,這個(gè)也只是猜測,其實(shí)我力推的優(yōu)化是(2,3)可惜沒有4一直超時(shí)。
還有就是一定要明確,連連看是存在決策問題的。
#include<map>
#include<queue>
#include<stdio.h>
#include<string.h>
#include<string>
using namespace std;
typedef struct
{
? ? int x ,y ,t;
}NODE;
typedef struct
{
? ? int x ,y;
}CARD;
NODE xin ,tou;
CARD card[105];
CARD can[105];
int ss[5];
int cans ,mkans ,n ,m ,nowc ,cards;
int _map[12][12];
int dir[4][2] = {0 ,1 ,0 ,-1 ,1 ,0 ,-1 ,0};
map<string ,int>MARK;
bool ok(int x ,int y)
{
? ? return x >= 1 && x <= n && y >= 1 && y <= m && (!_map[x][y] || _map[x][y] == nowc);
}
bool jude()
{
? ? char str[105];
? ? for(int i = 1 ;i <= cards ;i ++)
? ? if(_map[card[i].x][card[i].y]) str[i-1] = 'a';
? ? else str[i-1] = 'b';
? ? str[cards] = '\0';
? ? if(MARK[str]) return 0;
? ? MARK[str] = 1;
? ? return 1;
}
int BFS(int x ,int y)
{
? ? int mark[12][12] = {0};
? ? nowc = _map[x][y];
? ? cans = 0;
? ? xin.x = x ,xin.y = y ,xin.t = 0;
? ? queue<NODE>q;
? ? q.push(xin);
? ? while(!q.empty())
? ? {
? ? ? ? tou = q.front();
? ? ? ? q.pop();
? ? ? ? if(_map[tou.x][tou.y] == nowc && !(tou.x == x && tou.y == y))
? ? ? ? {
? ? ? ? ? ? cans ++;
? ? ? ? ? ? can[cans].x = tou.x;
? ? ? ? ? ? can[cans].y = tou.y;
? ? ? ? ? ? continue;
? ? ? ? }
? ? ? ? if(tou.t >= 3) continue;
? ? ? ? for(int i = 0 ;i < 4 ;i ++)
? ? ? ? {
? ? ? ? ? ? xin.x = tou.x ,xin.y = tou.y ,xin.t = tou.t + 1;
? ? ? ? ? ? while(1)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? xin.x += dir[i][0];
? ? ? ? ? ? ? ? xin.y += dir[i][1];
? ? ? ? ? ? ? ? if(!ok(xin.x ,xin.y)) break;
? ? ? ? ? ? ? ? if(!mark[xin.x][xin.y])
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? mark[xin.x][xin.y] = 1;
? ? ? ? ? ? ? ? ? ? q.push(xin);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? }
? ? }
? ? return cans;
}
bool CCC(int a ,int b)
{
? ? for(int i = 1 ;i <= cards ;i ++)
? ? {
? ? ? ? int x = card[i].x ,y = card[i].y;
? ? ? ? if(_map[x][y] == a)
? ? ? ? {
? ? ? ? ? ? if(_map[x+1][y+1] == a && _map[x+1][y] == b && _map[x][y+1] == b)
? ? ? ? ? ? return 1;
? ? ? ? ? ? return 0;
? ? ? ? }
? ? ? ? if(_map[x][y] == b)
? ? ? ? {
? ? ? ? ? ? if(_map[x+1][y+1] == b && _map[x+1][y] == a && _map[x][y+1] == a)
? ? ? ? ? ? return 1;
? ? ? ? ? ? return 0;
? ? ? ? }
? ? }
}
bool CUT()
{
? ? for(int i = 1 ;i <= 4 ;i ++)
? ? for(int j = i + 1 ;j <= 4 ;j ++)
? ? {
? ? ? ? if(ss[i] == ss[j] && ss[i] == 2)
? ? ? ? {
? ? ? ? ? ? if(CCC(i ,j)) return 1;
? ? ? ? }
? ? }
? ? return 0;
}
void DFS(int nows)
{
? ? if(!nows) mkans = 1;
? ? if(mkans) return ;
? ? if(!jude()) return ;
? ? if(CUT()) return ;
? ? for(int i = 1 ;i <= cards ;i ++)
? ? {
? ? ? ? if(mkans) return ;
? ? ? ? int x = card[i].x ,y = card[i].y;
? ? ? ? if(!_map[x][y]) continue;
? ? ? ? BFS(x ,y);
? ? ? ? ss[_map[x][y]] -= 2;
? ? ? ? for(int j = 1 ;j <= cans ;j ++)
? ? ? ? {
? ? ? ? ? ? int tmp = _map[x][y];
? ? ? ? ? ? int xx = can[j].x ,yy = can[j].y;
? ? ? ? ? ? _map[x][y] = _map[xx][yy] = 0;
? ? ? ? ? ? DFS(nows - 2);
? ? ? ? ? ? _map[x][y] = _map[xx][yy] = tmp;
? ? ? ? }
? ? ? ? ss[_map[x][y]] += 2;
? ? }
}
int main ()
{
? ? char str[12];
? ? while(~scanf("%d %d" ,&n ,&m) && n + m)
? ? {
? ? ? ? memset(_map ,0 ,sizeof(_map));
? ? ? ? memset(ss ,0 ,sizeof(ss));
? ? ? ? cards = 0;
? ? ? ? for(int i = 1 ;i <= n ;i ++)
? ? ? ? {
? ? ? ? ? ? scanf("%s" ,str);
? ? ? ? ? ? for(int j = 1 ;j <= m ;j ++)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? if(str[j-1] == '*') _map[i][j] = 0;
? ? ? ? ? ? ? ? else
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? _map[i][j] = str[j-1] - 'A' + 1;
? ? ? ? ? ? ? ? ? ? cards ++;
? ? ? ? ? ? ? ? ? ? card[cards].x = i;
? ? ? ? ? ? ? ? ? ? card[cards].y = j;
? ? ? ? ? ? ? ? ? ? ss[_map[i][j]] ++;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? if(ss[1]%2 || ss[2]%2 || ss[3]%2 || ss[4]%2)
? ? ? ? {
? ? ? ? ? ? printf("no\n");
? ? ? ? ? ? continue;
? ? ? ? }
? ? ? ? mkans = 0;
? ? ? ? MARK.clear();
? ? ? ? DFS(cards);
? ? ? ? mkans ? printf("yes\n"):printf("no\n");
? ? }
? ? return 0;
}
總結(jié)
以上是生活随笔為你收集整理的POJ2308连连看dfs+bfs+优化的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: POJ1789简单小生成树
- 下一篇: POJ2349二分+并查集,类似最小树的