圖論算法

一介褥、并查集
?并查集迹冤,在一些有N個元素的集合應(yīng)用問題中嚣州,我們通常是在開始時讓每個元素構(gòu)成一個單元素的集合,然后按一定順序?qū)儆谕唤M的元素所在的集合合并硝拧,其間要反復(fù)查找一個元素在哪個集合中径筏。這一類問題近幾年來反復(fù)出現(xiàn)在信息學(xué)的國際國內(nèi)賽題中,其特點是看似并不復(fù)雜障陶,但數(shù)據(jù)量極大滋恬,若用正常的數(shù)據(jù)結(jié)構(gòu)來描述的話,往往在空間上過大抱究,計算機無法承受恢氯;即使在空間上勉強通過,運行的時間復(fù)雜度也極高鼓寺,根本就不可能在比賽規(guī)定的運行時間(1~3秒)內(nèi)計算出試題需要的結(jié)果勋拟,只能用并查集來描述。
?例如:若某個家族人員過于龐大妈候,要判斷兩個是否是親戚敢靡,確實還很不容易,給出某個親戚關(guān)系圖州丹,求任意給出的兩個人是否具有親戚關(guān)系醋安。 規(guī)定:x和y是親戚杂彭,y和z是親戚,那么x和z也是親戚吓揪。如果x,y是親戚,那么x的親戚都是y的親戚柠辞,y的親戚也都是x的親戚。
?算法:
(1) 開始時叭首,為每個人建立一個集合Set(x);
(2) 得到一個關(guān)系后a,b图毕,合并相應(yīng)集合Union(a,b)眷唉;

題目描述:某省調(diào)查城鎮(zhèn)交通狀況,得到現(xiàn)有城鎮(zhèn)道路統(tǒng)計表冬阳,表中列出了每條道路直接連通的城鎮(zhèn)。省政府“暢通工程”的目標(biāo)是使全省任何兩個城鎮(zhèn)間都可以實現(xiàn)交通(但不一定有直接的道路相連驳庭,只要互相間接通過道路可達即可)。問最少還需要建設(shè)多少條道路饲常?
輸入描述:
測試輸入包含若干測試用例。每個測試用例的第1行給出兩個正整數(shù)荞驴,分別是城鎮(zhèn)數(shù)目N ( < 1000 )和道路數(shù)目M不皆;隨后的M行對應(yīng)M條道路,每行給出一對正整數(shù)熊楼,分別是該條道路直接連通的兩個城鎮(zhèn)的編號霹娄。為簡單起見,城鎮(zhèn)從1到N編號鲫骗。
注意:兩個城市之間可以有多條道路相通,也就是說
3 3
1 2
1 2
2 1
這種輸入也是合法的
當(dāng)N為0時犬耻,輸入結(jié)束,該用例不被處理执泰。
輸出描述:
對每個測試用例枕磁,在1行里輸出最少還需要建設(shè)的道路數(shù)目。
示例輸入:
4 2
1 3
4 3
3 3
1 2
1 3
2 3
5 2
1 2
3 5
999 0
0
示例輸出:
1
0
2
998

#include<iostream>
#include<vector>
using namespace std;
int roads[1001];
int main(){
    while (true){
        int n, m;
        cin >> n;
        if (n == 0){
            return 0;
        }
        cin >> m;
        for (int i = 1; i <= n; i++){
            roads[i] = -1;
        }
        for (int i = 0; i < m; i++){
            int a, b;
            cin >> a >> b;
            int max = roads[a] > roads[b] ? roads[a] : roads[b];
            if (max == -1){
                roads[a] = b;
            }
            else{
                int ai = a;
                int bi = b;
                while (roads[ai] != -1){
                    ai = roads[ai];
                }
                while (roads[bi] != -1){
                    bi = roads[bi];
                }
                if (ai != bi){
                    roads[bi] = ai;
                }
            }
        }
        int sum = 0;
        for (int i = 1; i <= n; i++){
            if (roads[i] == -1){
                sum++;
            }
        }
        cout << sum - 1 << endl;
    }
    return 0;
}

二术吝、最小生成樹
?根據(jù)Kruskal算法可以生成最小生成樹计济,即每次選取最小權(quán)重的邊茸苇,若不成環(huán),則加入集合沦寂。而檢測是否成環(huán)可以根據(jù)并查集進行計算学密。

題目描述:
?某省調(diào)查鄉(xiāng)村交通狀況,得到的統(tǒng)計表中列出了任意兩村莊間的距離传藏。省政府“暢通工程”的目標(biāo)是使全省任何兩個村莊間都可以實現(xiàn)公路交通(但不一定有直接的公路相連腻暮,只要能間接通過公路可達即可),并要求鋪設(shè)的公路總長度為最小毯侦。請計算最小的公路總長度哭靖。
輸入描述:
?測試輸入包含若干測試用例。每個測試用例的第1行給出村莊數(shù)目N ( < 100 )侈离;隨后的N(N-1)/2行對應(yīng)村莊間的距離试幽,每行給出一對正整數(shù),分別是兩個村莊的編號卦碾,以及此兩村莊間的距離蔗坯。為簡單起見宾濒,村莊從1到N編號绘梦。
?當(dāng)N為0時,輸入結(jié)束榄棵,該用例不被處理疹鳄。
輸出描述:
?對每個測試用例瘪弓,在1行里輸出最小的公路總長度腺怯。
示例輸入:
3
1 2 1
1 3 2
2 3 4
4
1 2 1
1 3 4
1 4 1
2 3 3
2 4 2
3 4 5
0
輸出:
3
5

備注:
采用<algorithm>頭文件中的sort函數(shù)虑乖,可以進行遞增排序决左。
根據(jù)需要重載 < :
bool operator < (const Template &A) const{} 
#include<iostream>
#include<algorithm>
using namespace std;
int roads[101];
struct Node{
    int a, b;
    int cost;
    bool operator < (const Node &A) const {
        return cost < A.cost;
    }
}node[5000];
int findroot(int a){
    if (roads[a] == -1)
        return a;
    int i = a;
    while (roads[i] != -1){
        i = roads[i];
    }
    //roads[a] = i;
    return i;
}
bool unionset(Node nd){
    int aroot = findroot(nd.a);
    int broot = findroot(nd.b);
    if (aroot != broot){
        roads[aroot] = broot;
        return true;
    }
    else{
        return false;
    }
}
int main(){
    while (true){
        int n;
        cin >> n;
        if (n == 0){
            return 0;
        }
        int times = n*(n - 1) / 2;
        for (int i = 1; i <= n; i++){
            roads[i] = -1;
        }
        for (int i = 0; i < times; i++){
            cin >> node[i].a >> node[i].b >> node[i].cost;
        }
        sort(node,node+times);
        int iter = 1;
        int sum = 0;
        for (int i = 0; iter < n; i++){
            if (unionset(node[i])){
                iter++;
                sum += node[i].cost; 
            }
        }
        cout << sum << endl;
    }
    return 0;
}

三、最短路徑

題目描述:
?在每年的校賽里继找,所有進入決賽的同學(xué)都會獲得一件很漂亮的t-shirt婴渡。但是每當(dāng)我們的工作人員把上百件的衣服從商店運回到賽場的時候边臼,卻是非常累的柠并!所以現(xiàn)在他們想要尋找最短的從商店到賽場的路線,你可以幫助他們嗎啃沪?
輸入描述:
?輸入包括多組數(shù)據(jù)创千。每組數(shù)據(jù)第一行是兩個整數(shù)N追驴、M(N<=100氯檐,M<=10000)冠摄,N表示成都的大街上有幾個路口,標(biāo)號為1的路口是商店所在地沃呢,標(biāo)號為N的路口是賽場所在地某抓,M則表示在成都有幾條路否副。N=M=0表示輸入結(jié)束备禀。接下來M行曲尸,每行包括3個整數(shù)A另患,B柴淘,C(1<=A,B<=N,1<=C<=1000),表示在路口A與路口B之間有一條路敛熬,我們的工作人員需要C分鐘的時間走過這條路。
?輸入保證至少存在1條商店到賽場的路線话原。
輸出描述:
?對于每組輸入,輸出一行黄虱,表示工作人員從商店走到賽場的最短時間
示例輸入:
2 1
1 2 3
3 3
1 2 5
2 3 5
3 1 2
0 0
輸出:
3
2

#include<iostream>
using namespace std;
const int NOWAY = -1;
const int VNUM = 101;
// 鄰接矩陣
int cost[VNUM][VNUM];

// Floyd算法
// cost[k][i][j] = min { cost[k-1][i][j], 
//      cost[k-1][i][k] + cost[kNOWAY][k][j] }
//  從i到j(luò)且中間節(jié)點最大不超過k
//  第一維數(shù)組可優(yōu)化
void floyd(int n){
    for (int k = 1; k <= n; k++){
        for (int i = 1; i <= n; i++){
            for (int j = 1; j <= n; j++){
                if (cost[i][k]!=NOWAY && cost[k][j]!=NOWAY){
                    if (cost[i][j] == NOWAY || cost[i][j] > cost[i][k] + cost[k][j]){
                        cost[i][j] = cost[i][k] + cost[k][j];
                    }
                }
            }
        }
    }
    if (cost[1][n] != NOWAY){
        cout << cost[1][n] << endl;
    }
}
// Dijkstra算法
// 從一個節(jié)點出發(fā)捻浦,不斷迭代最短距離昧识。
// 從length[]中選取最小長度對應(yīng)的結(jié)點J,加入新結(jié)點j跪楞。
// 更新length[]甸祭。 a[k] = min { a[j] + cost[j][k] }
// 循環(huán)N次
bool mark[VNUM]; // 記錄節(jié)點是否已加入
int length[VNUM];
void dijkstra(int n, int begin,int end){
    for (int i = 1; i <= n; i++){
        length[i] = -1;
        mark[i] = false;
    }
    // 加入開始節(jié)點
    mark[begin] = true;
    length[begin] = 0;
    int newp = begin;

    // 不斷加入新節(jié)點淋叶,循環(huán)加入n次
    for (int i = 1; i <= n; i++){
        for (int j = 1; j <= n; j++){

            // 根據(jù)新加的節(jié)點的邊煞檩,更新距離數(shù)組
            if (mark[j] || cost[newp][j] == -1){
                continue;
            }
            // 如果節(jié)點j不可達斟湃,但是newp可達凝赛;或者
            // length[j]>length[newp]+cost[newp][j] 更新墓猎。
            if (length[j]==-1||length[j]>length[newp]+cost[newp][j]){
                length[j] = length[newp] + cost[newp][j];
            }
        }
        // 尋找未加入的節(jié)點中最短路對應(yīng)的節(jié)點毙沾,當(dāng)作新加入的節(jié)點。
        int min = 999999999;
        for (int k = 1; k <= n; k++){
            if (!mark[k] && length[k] != -1 && length[k] < min){
                min = length[k];
                newp = k;
            }
        }
        mark[newp] = true;
    }
    cout << length[end] << endl;
}
int main(){
    while (true){
        int n, m;
        cin >> n >> m;
        if (n == 0 && m == 0){
            return 0;
        }
        int a, b, c;
        for (int i = 1; i <= n; i++){
            for (int j = 1; j <= n; j++){
                cost[i][j] = NOWAY;
            }
            cost[i][i] = 0;
        }
        for (int i = 0; i < m; i++){
            cin >> a >> b >> c;
            cost[a][b] = c;
            cost[b][a] = c;
        }
        // floyd(n);
        dijkstra(n, 1, n);
    }
    return 0;

}

四烤宙、拓?fù)渑判?/strong>

題目描述:
?有N個比賽隊(1<=N<=500),編號依次為1屯远,2慨丐,3备闲,恬砂。泻骤。。亲轨。器虾,N進行比賽兆沙,比賽結(jié)束后葛圃,裁判委員會要將所有參賽隊伍從前往后依次排名,但現(xiàn)在裁判委員會不能直接獲得每個隊的比賽成績尚氛,只知道每場比賽的結(jié)果阅嘶,即P1贏P2抡蛙,用P1粗截,P2表示,排名時P1在P2之前∈幔現(xiàn)在請你編程序確定排名昂利。
輸入描述:
?輸入有若干組,每組中的第一行為二個數(shù)N(1<=N<=500)窝撵,M;其中N表示隊伍的個數(shù)襟铭,M表示接著有M行的輸入數(shù)據(jù)碌奉。接下來的M行數(shù)據(jù)中,每行也有兩個整數(shù)P1寒砖,P2表示即P1隊贏了P2隊赐劣。
輸出描述:
?給出一個符合要求的排名。輸出時隊伍號之間有空格哩都,最后一名后面沒有空格魁兼。
其他說明:
?符合條件的排名可能不是唯一的,此時要求輸出時編號小的隊伍在前漠嵌;輸入數(shù)據(jù)保證是正確的,即輸入數(shù)據(jù)確保一定能有一個符合要求的排名蟹瘾。
示例輸入:
4 3
1 2
2 3
4 3
輸出:
1 2 4 3

// 不斷尋找入度為0的頂點。
#include<iostream>
using namespace std;
const int VNUM = 501;
int cost[VNUM][VNUM];
int in[VNUM];
int ans[VNUM];
void topo(int n){
    int index = 1;
    for (int k = 0; k < n; k++){
        for (int i = 1; i <= n; i++){
            if (in[i] == 0){
                ans[index] = i;
                for (int j = 1; j <= n; j++){
                    if (cost[i][j] == 1){
                        in[j]--;
                    }
                }
                in[i] = -1;
                index++;
                break;
            }
        }
    }
    for (int i = 1; i < n; i++){
        cout << ans[i] << " ";
    }
    cout <<ans[n]<< endl;
}
int main(){
    int n, m;
    while (cin >> n >> m){
        int a, b;
        for (int i = 1; i <= n; i++){
            for (int j = 1; j <= n; j++){
                cost[i][j] = 0;
            }
            in[i] = 0;
        }
        for (int i = 0; i < m; i++){
            cin >> a >> b;
            // 防止重邊
            if (cost[a][b] == 0)
                in[b]++;
            cost[a][b] = 1;
        }
        topo(n);
    }
    return 0;
}

五、廣度優(yōu)先搜索和深度優(yōu)先搜索

問題描述:(勝利大逃亡)
?Ignatius被魔王抓走了,有一天魔王出差去了,這可是Ignatius逃亡的好機會.
?魔王住在一個城堡里,城堡是一個ABC的立方體,可以被表示成A個B*C的矩陣,剛開始Ignatius被關(guān)在(0,0,0)的位置,離開城堡的門在(A-1,B-1,C-1)的位置,現(xiàn)在知道魔王將在T分鐘后回到城堡,Ignatius每分鐘能從一個坐標(biāo)走到相鄰的六個坐標(biāo)中的其中一個.現(xiàn)在給你城堡的地圖,請你計算出Ignatius能否在魔王回來前離開城堡(只要走到出口就算離開城堡,如果走到出口的時候魔王剛好回來也算逃亡成功),如果可以請輸出需要多少分鐘才能離開,如果不能則輸出-1.


輸入:
?輸入數(shù)據(jù)的第一行是一個正整數(shù)K,表明測試數(shù)據(jù)的數(shù)量.每組測試數(shù)據(jù)的第一行是四個正整數(shù)A,B,C和T(1<=A,B,C<=50,1<=T<=1000),它們分別代表城堡的大小和魔王回來的時間.然后是A塊輸入數(shù)據(jù)(先是第0塊,然后是第1塊,第2塊......),每塊輸入數(shù)據(jù)有B行,每行有C個正整數(shù),代表迷宮的布局,其中0代表路,1代表墻.(如果對輸入描述不清楚,可以參考Sample Input中的迷宮描述,它表示的就是上圖中的迷宮)
特別注意:本題的測試數(shù)據(jù)非常大,請使用scanf輸入,我不能保證使用cin能不超時.在本OJ上請使用Visual C++提交.

輸出:
?對于每組測試數(shù)據(jù),如果Ignatius能夠在魔王回來前離開城堡,那么請輸出他最少需要多少分鐘,否則輸出-1.

Sample Input

1
3 3 4 20
0 1 1 1
0 0 1 1
0 1 1 1
1 1 1 1
1 0 0 1
0 1 1 1
0 0 0 0
0 1 1 0
0 1 1 0

Sample Output
11

解題思路:DFS芦圾,每次向六個方向擴展,時間加1,采用queue數(shù)據(jù)結(jié)構(gòu),第一次遍歷到出口 時即最短時間弃酌。
問題:第一段是網(wǎng)上答案乌询,第二段是我的代碼鬼佣。我的代碼一直出現(xiàn)內(nèi)存超限税迷,暫未找到原因。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <algorithm>
#include <math.h>
#include <queue>
using namespace std;
bool mark[50][50][50];
bool m[50][50][50];
int t;
int go[][3] =
{
    1, 0, 0,
    -1, 0, 0,
    0, 1, 0,
    0, -1, 0,
    0, 0, 1,
    0, 0, -1
};
struct e
{
    int x, y, z;
    int t;
};
queue <e> q;
int bfs(int a, int b, int c)
{
    while (!q.empty())
    {
        e now;
        now = q.front();
        q.pop();
        if (now.t >= t) {
            return  -1;
        }
        for (int i = 0; i<6; i++)
        {
            int nx = now.x + go[i][0];
            int ny = now.y + go[i][1];
            int nz = now.z + go[i][2];
            if (nx<0 || nx >= a || ny<0 || ny >= b || nz<0 || nz >= c) continue;
            if (mark[nx][ny][nz] == 1) continue;
            if (m[nx][ny][nz] == 1) continue;
            m[nx][ny][nz] = 1;
            e tmp;
            tmp.x = nx;
            tmp.y = ny;
            tmp.z = nz;
            tmp.t = now.t + 1;
            if (tmp.t <t) {
                q.push(tmp);
            }
            mark[nx][ny][nz] == 1;
            if (nx == a - 1 && ny == b - 1 && nz == c - 1)
                return tmp.t;
        }
    }
    return -1;
}
int main()
{
    int a, b, c;
    int k;
    while (scanf_s("%d", &k) != eof)
    {
        while (k--)
        {
            scanf_s("%d%d%d%d", &a, &b, &c, &t);
            for (int i = 0; i<a; i++)
            {
                for (int j = 0; j<b; j++)
                {
                    for (int k = 0; k<c; k++)
                    {
                        scanf_s("%d", &m[i][j][k]);
                        mark[i][j][k] = 0;
                    }
                }
            }
            while (!q.empty()) q.pop();
            e tmp;
            tmp.x = tmp.y = tmp.z = tmp.t = 0;
            q.push(tmp);
            mark[0][0][0] = 1;
            int rec = bfs(a, b, c);
            if (rec <= t && rec != -1) printf("%d\n", rec);
            else printf("-1\n");
        }
    }
    return 0;
}
#include<iostream>
#include<queue>
using namespace std;
const int MAX = 50;
int map[MAX][MAX][MAX];
bool mark[MAX][MAX][MAX];
int A, B, C, T;
struct Dot{
    int a;
    int b;
    int c;
    int t;
};
queue<Dot> Q;
void BFS(){
    while (Q.empty() == false){
        Dot dot = Q.front();
        int a = dot.a;
        int b = dot.b;
        int c = dot.c;
        int t = dot.t;
        if (a == A - 1 && b == B - 1 && c == C - 1 && !mark[a][b][c]){
            mark[a][b][c] = true;
            if (t <= T)
                cout << t << endl;
            else
                cout << -1 << endl;
            return;
        }
        if (t > T){
            cout << -1 << endl;
            return;
        }
        mark[a][b][c] = true;
        Dot temp;
        if (a > 0 && !mark[a - 1][b][c] && map[a - 1][b][c] == 0){
            temp.t = t + 1;
            temp.a = a - 1;
            temp.b = b;
            temp.c = c;
            Q.push(temp);
        }
        if (a<A-1&&!mark[a + 1][b][c] && map[a + 1][b][c] == 0){
            temp.t = t + 1;
            temp.a = a + 1;
            temp.b = b;
            temp.c = c;
            Q.push(temp);
        }
        if (b > 0 && !mark[a][b - 1][c] && map[a][b - 1][c] == 0){
            temp.t = t + 1;
            temp.a = a;
            temp.b = b-1;
            temp.c = c;
            Q.push(temp);
        }
        if (b<B-1&&map[a][b + 1][c] == 0 && !mark[a][b + 1][c]){
            temp.t = t + 1;
            temp.a = a ;
            temp.b = b+1;
            temp.c = c;
            Q.push(temp);
        }
        if (c > 0 && !mark[a][b][c - 1] && map[a][b][c - 1] == 0){
            temp.t = t + 1;
            temp.a = a;
            temp.b = b;
            temp.c = c-1;
            Q.push(temp);
        }
        if (c<C-1&&map[a][b][c + 1] == 0 && !mark[a][b][c + 1]){
            temp.t = t + 1;
            temp.a = a;
            temp.b = b;
            temp.c = c + 1;
            Q.push(temp);
        }
        Q.pop();
    }
}
int main(){
    int n;
    while (scanf_s("%d", &n) != EOF){
        scanf_s("%d%d%d%d", &A, &B, &C, &T);
        for (int i = 0; i < A; i++)
        {
            for (int j = 0; j < B; j++)
            {
                for (int k = 0; k < C; k++)
                {
                    map[i][j][k] = 0;
                    // cin >> map[i][j][k];
                    scanf_s("%d", &map[i][j][k]);
                    mark[i][j][k] = 0;
                }
            }
        }
        while (!Q.empty()){
            Q.pop();
        }
        Dot d;
        d.a = 0;
        d.b = 0;
        d.c = 0;
        d.t = 0;
        map[0][0][0] = 0;
        Q.push(d);
        BFS();
        if (!mark[A - 1][B - 1][C - 1])
            cout << -1 << endl;
    }
    return 0;
}

Problem Description(非吃钐澹可樂)
?大家一定覺的運動以后喝可樂是一件很愜意的事情,但是seeyou卻不這么認(rèn)為。因為每次當(dāng)seeyou買了可樂以后疲吸,阿牛就要求和seeyou一起分享這一瓶可樂,而且一定要喝的和seeyou一樣多孵运。但seeyou的手中只有兩個杯子,它們的容量分別是N 毫升和M 毫升 可樂的體積為S (S<101)毫升 (正好裝滿一瓶) 咐熙,它們?nèi)齻€之間可以相互倒可樂 (都是沒有刻度的去团,且 S==N+M鞋吉,101>S>0,N>0改抡,M>0) 欠拾。聰明的ACMER你們說他們能平分嗎荆忍?如果能請輸出倒可樂的最少的次數(shù),如果不能輸出"NO"岳守。

Input
?三個整數(shù) : S 可樂的體積 , N 和 M是兩個杯子的容量佣赖,以"0 0 0"結(jié)束。

Output
?如果能平分的話請輸出最少要倒的次數(shù)记盒,否則輸出"NO"憎蛤。

Sample Input
7 4 3
4 1 3
0 0 0

Sample Output
NO
3

#include<iostream>
#include<queue>
using namespace std;
struct Liquid{
    int n;
    int m;
    int s;
    int times;
};
bool mark[101][101][101];
queue<Liquid> Q;
int N, M, S;
void AtoB(int &a, int &b, int max){
    if (a + b > max){
        a = a + b - max;
        b = max;
    }
    else{
        b = a + b;
        a = 0;
    }
}
void push_back(int n, int m, int s, int t){
    if (n > N || m > M || s > S){
        return;
    }
    Liquid next ;
    if (mark[n][m][s] == false){
        next.n = n;
        next.m = m;
        next.s = s;
        next.times = t + 1;
        Q.push(next);
    }
}
int main(){
    while (true){
        cin >> S >> N >> M;
        bool flag = false;
        if (S == 0 && N == 0 && M == 0){
            return 0;
        }
        if (S % 2 != 0){
            cout << "NO" << endl;
            continue;
        }
        for (int i = 0; i <= N; i++){
            for (int j = 0; j <= M; j++){
                for (int k = 0; k <= S; k++)
                    mark[i][j][k] = 0;
            }
        }
        while (!Q.empty()){
            Q.pop();
        }
        Liquid temp;
        temp.n = 0;
        temp.m = 0;
        temp.s = S;
        temp.times = 0;
        Q.push(temp);
        while (Q.empty() == false){
            Liquid now = Q.front();
            Liquid next;
            Q.pop();
            int n, m, s, t;
            n = now.n;
            m = now.m;
            s = now.s;
            t = now.times;

            mark[n][m][s] = true;
            if ((n == S / 2 && m == S / 2) || (n == S / 2 && s == S / 2) || (m == S / 2 && s == S / 2)){
                cout << t << endl;
                flag = true;
                break;
            }
            AtoB(n, m, M);
            push_back(n, m, s, t);


            n = now.n;
            m = now.m;
            s = now.s;
            t = now.times;
            AtoB(n, s, S);
            push_back(n, m, s, t);


            n = now.n;
            m = now.m;
            s = now.s;
            t = now.times;
            AtoB(m, n, N);
            push_back(n, m, s, t);


            n = now.n;
            m = now.m;
            s = now.s;
            t = now.times;
            AtoB(m, s, S);
            push_back(n, m, s, t);


            n = now.n;
            m = now.m;
            s = now.s;
            t = now.times;
            AtoB(s, m, M);
            push_back(n, m, s, t);


            n = now.n;
            m = now.m;
            s = now.s;
            t = now.times;
            AtoB(s, n, N);
            push_back(n, m, s, t);


        }
        if (flag)
            continue;
        cout << "NO" << endl;
    }
    return 0;
}
此類題目應(yīng)先確認(rèn)狀態(tài)的轉(zhuǎn)移關(guān)系。
(x,y,z...) ---> (xx,yy,zz...).。
其次找清判斷結(jié)果的條件俩檬。

六萎胰、A*算法(拓展)
綜合了DFS/BFS和啟發(fā)式尋路算法。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末棚辽,一起剝皮案震驚了整個濱河市技竟,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌屈藐,老刑警劉巖榔组,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異联逻,居然都是意外死亡搓扯,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進店門遣妥,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人攀细,你說我怎么就攤上這事箫踩。” “怎么了谭贪?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵境钟,是天一觀的道長。 經(jīng)常有香客問我俭识,道長慨削,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任套媚,我火速辦了婚禮缚态,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘堤瘤。我一直安慰自己玫芦,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布本辐。 她就那樣靜靜地躺著桥帆,像睡著了一般。 火紅的嫁衣襯著肌膚如雪慎皱。 梳的紋絲不亂的頭發(fā)上老虫,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天,我揣著相機與錄音茫多,去河邊找鬼祈匙。 笑死,一個胖子當(dāng)著我的面吹牛天揖,可吹牛的內(nèi)容都是我干的菊卷。 我是一名探鬼主播缔恳,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼洁闰!你這毒婦竟也來了歉甚?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤扑眉,失蹤者是張志新(化名)和其女友劉穎纸泄,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體腰素,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡聘裁,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了弓千。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片衡便。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖洋访,靈堂內(nèi)的尸體忽然破棺而出镣陕,到底是詐尸還是另有隱情,我是刑警寧澤姻政,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布呆抑,位于F島的核電站,受9級特大地震影響汁展,放射性物質(zhì)發(fā)生泄漏鹊碍。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一食绿、第九天 我趴在偏房一處隱蔽的房頂上張望侈咕。 院中可真熱鬧,春花似錦器紧、人聲如沸乎完。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽树姨。三九已至,卻和暖如春桥状,著一層夾襖步出監(jiān)牢的瞬間帽揪,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工辅斟, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留转晰,地道東北人。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像查邢,于是被迫代替她去往敵國和親蔗崎。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內(nèi)容