ZOJ 1301 The New Villa (BFS + 状态压缩)

题意:黑先生新买了一栋别墅,可是里面的电灯线路的连接是很混乱的(每个房间的开关可能控制其他房间,房间数<=10),有一天晚上他回家时发现所有的灯(除了他出发的房间)都是关闭的,而他想回卧室去休息。可是很不幸,他十分怕黑,因此他不会走入任何关着灯的房间,于是请你帮他找出一条路使他既能回到卧室又能关闭除卧室以外的所有灯。如果同时有好几条路线的话,请输出最短的路线。(ZOJ是special judge,poj不是)

写起来有些纠结(实力太弱)...........先对各个房间的灯进行操作,再考虑向其他房间走的问题。

由于要输出路径,所以添加前驱标识,递归输出即可。

#include <cstdio>
#include <iostream>
#include <cmath>
#include <cstring>
using namespace std;
int n,m,p;
int ed1[11][11],ed2[11][11];
int vis[11][1 << 10];
struct node {
    int s,e,pre,op,step,buff;
    void _init() {
        pre = -1;
        step = 0;
        buff = 1;
        op = -1;
    }
} q[55555];
int head,tail;
void init() {
    head = 0;
    tail = 0;
    memset(vis,0,sizeof(vis));
    memset(ed1,0,sizeof(ed1));
    memset(ed2,0,sizeof(ed2));
}

int bfs(int v0) {
    vis[v0][1] = 1;
    q[0]._init();
    q[0].s = 1;
    head ++;
    while(head != tail) {
        node t = q[tail++];
        node tt;
        if(t.s == n && t.buff == (1 << (n-1))) { // find it
            return tail - 1;
        }
        for(int i=1; i<=n; i++) {
            int move = 1 << (i-1);
            tt = t;
            if(ed2[t.s][i] == 1 && i != t.s && vis[t.s][t.buff ^ move] == 0) { // 对房间的灯进行操作
                vis[t.s][t.buff ^ move] = 1;
                tt.buff = t.buff ^ move;
                tt.step = t.step + 1;
                tt.pre = tail - 1;
                tt.e = i;  
                if(tt.buff & move) tt.op = 1; //开灯
                else tt.op = 0; //关灯
                q[head++] = tt;
            }
        }
        for(int i=1; i<=n; i++) { //向其他房间前行
            tt = t;
            tt.step = t.step + 1;
            if(ed1[t.s][i] == 1 && vis[i][t.buff] == 0 && (t.buff & (1 << (i-1)))) {
                vis[i][t.buff] = 1;
                tt.s = i;
                tt.e = i;
                tt.pre = tail - 1;
                tt.op = 2; // 移动
                q[head++] = tt;
            }
        }
    }
    return -1;
}

void print(int v0) {
    if(v0 == -1) return ;
    print(q[v0].pre);
    if(q[v0].op == 0) printf("- Switch off light in room %d.
",q[v0].e);
    if(q[v0].op == 1) printf("- Switch on light in room %d.
",q[v0].e);
    if(q[v0].op == 2) printf("- Move to room %d.
",q[v0].e);
}
int main() {
#ifndef ONLINE_JUDGE
    freopen("D:\in.txt","r",stdin);
    freopen("D:\out2.txt","w",stdout);
#endif
    int a,b;
    int casee = 1;
    while(scanf("%d%d%d",&n,&m,&p) != EOF) {
        if(n == 0 && m == 0 && p == 0) break; //之前没看清题目,wa的无语了
        init();
        for(int i=0; i<m; i++) {
            scanf("%d%d",&a,&b);
            ed1[a][b] = 1;
            ed1[b][a] = 1;
        }
        for(int i=0; i<p; i++) {
            scanf("%d%d",&a,&b);
            ed2[a][b] = 1;
        }
        printf("Villa #%d
",casee ++);
        int final = bfs(1);
        if(final >= 0) {
            printf("The problem can be solved in %d steps:
",q[final].step);
            print(final);
        } else {
            printf("The problem cannot be solved.
");
        }
        puts("");
    }
    return 0;
}


原文地址:https://www.cnblogs.com/pangblog/p/3260524.html