zoukankan      html  css  js  c++  java
  • FZU 2093 找兔子 状压DP

    题目链接:找兔子

    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
    ";
            }
            else cout << ans << endl;
        }
        return 0;
    }
    

      

  • 相关阅读:
    java数据库访问类和接口
    数据删除的用法
    短信发送(M800)
    Spring注解开发(六)扩展原理
    观察者模式(Obeserver Pattern)
    Spring注解开发(五)声明式事务
    Spring注解开发(四)AOP原理与源码分析
    Spring注解开发(三)属性赋值与自动装配
    Spring注解开发(二)生命周期
    Spring注解开发(一)组件注册
  • 原文地址:https://www.cnblogs.com/icode-girl/p/5395034.html
Copyright © 2011-2022 走看看