题目链接:找兔子

n的范围是[1, 15],可以用0 到 (1<<n)-1 的数表示全部状态,用dp[i] = t表示到达状态i的最少时间是t,对于每个点,如果它能到达的所有点在t秒时都已经确定了会不会有兔纸,那这个点就确定了在(t+1)s会不会有兔纸。对于每个时刻,可以询问<=2个点,所以由初始状态可以搜到最后确定能不能找到兔纸。

我没有想到找不到兔纸的数据...

关键是dp的思想==很巧妙。

附代码:

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <queue>
#define maxn 16
#define inf 10000000
using namespace std;

int edge[maxn]; // 储存每个点的边的信息
int dp[1<<maxn]; // dp[i]表示到达i状态的最少时间,一共有1<<n个状态 i的二进制中1表示已经确定了该点,0表示还没有

int main() {
    int t;
    cin >> t;
    while(t--) {
        int n, m;
        memset(edge, 0, sizeof(edge));
        cin >> n >> m;
        for (int i=0; i<=(1<<n); ++i) {
            dp[i] = inf;
        }

        for (int i=0; i<m; ++i) {
            int x, y;
            cin >> x >> y;
            x--, y--;
            edge[x] |= (1<<y);
            edge[y] |= (1<<x);
        }

        for (int i=0; i<n; ++i) {
            if (!edge[i]) edge[i] |= (1<<i);
        }

        queue<int>que;
        dp[0] = 0;
        que.push(0);

        while(!que.empty()) {
            int now = que.front();
            que.pop();
            int nxt = 0;

            for (int i=0; i<n; ++i) {
                if ((now&edge[i]) == edge[i]) {
                    nxt |= (1<<i); // 所有当前已经确定的点(不是状态)都保存在了nxt中。
                }
            }

            for (int i=0; i<n; ++i) {
                for (int j=i+1; j<n; ++j) {
                    int nxtstu = (nxt|(1<<i)|(1<<j)); //可以确定状态nxtstu 时间选择min
                    if (dp[nxtstu] > dp[now] + 1) {
                        dp[nxtstu] = dp[now] + 1;
                        que.push(nxtstu);// 如果当前状态更新 加入队列以更新它可以到达的状态
                    }
                }
            }
        }

        int tot = (1<<n)-1;
        int ans = dp[tot];  //全部点都确定的一个状态

        for (int i=0; i<n; ++i) {
            int stu = (tot^(1<<i)); //每个还有一个点没确定的状态
            ans = min(ans, dp[stu]);
        }

        if (ans == inf) {
            cout << "-1\n";
        }
        else cout << ans << endl;
    }
    return 0;
}

  

posted on 2016-04-15 13:04  小小八  阅读(253)  评论(0编辑  收藏  举报