zoukankan      html  css  js  c++  java
  • [noip模拟]食物中毒<暴搜+状压优化>

    问题描述

    Bqc经过一段时间的研究发现,要解这种毒需要一种特殊的药物。不幸的是,这种药物在 市面上不存在,没有办法Bqc只好亲自制得这种药物。它含有M种化学物质A1,A2,…,AM。现 在Bqc的手上有N种药材(每种药材只有一种),每种药材含有若干种化学物质(Bqc他有一种 机器,只要将药材放入机器,就能制得相应的药物)。

    Bqc需要你的帮助,他希望你能帮他选取若干种药材,用这些选取的药材制作出Bqc需要 的药物。由于这些化学物质是有毒的,因此你选出来的药物,必须含有这M种化学物质。 有一点需要注意:根据中医以毒攻毒的理论,两个相同的化学物质在一起,它们的药性会 同时消失变为一种无毒物质(大多情况下这种无毒物质会挥发掉,也就是说这种化学物质消 失了)。比如说药材1有化学物质1、2,药材2有化学物质1、3,那么如果药材1和药材2混合, 你得到的药物会含有化学物质2、3。 Bqc问你,需要选用那些药材可以制得他想要的药物?

    输入格式

      本题每个测试点存在多组数据,每组输入数据第1行包含两个整数N和M,表示Bqc拥有的 药材数目和他所需药物所含的化学物质的种类数目;

      第2行共有M个整数,分别表示M中化学物质的编号,用1~50之间的数字编号(输入数据保 证同一种化学物质不会被描述多次);

      第3行到第N+2行,每行包含若干个数。第i+2行的第一个数为Mi,表示药材i包含Mi中化 学物质,接下来Mi个数,描述药材i含有的化学物质的编号,用1~50之间的数字编号(同一种 化学物质可能会被描述多次)。  每组输入数据用一个空行隔开。

    输出格式

      对于每组数据输出一行,如果用这些药材可以制得Bqc需要的药物,那么输出“Possible”; 否则输出“Impossible”,不包含引号。

    样例输入

    2 2
    2 3
    2 1 5
    2 1 3

    3 3
    1 3 4
    4 2 3 4 1
    1 4
    2 2 1

    4 4
    1 2 3 4
    3 1 3 4
    3 1 4 5
    1 2
    2 2 3

    样例输出

    Impossible

    Possible

    Possible

    其实吧,这道题我把它画成图,我还以为可以用二分图匹配做,后来发现tan90°,然后就只有用状压了,毕竟这个选到指定种类的题很容易想到用二进制表示状态

    然后就是一个暴力搜索了,原本是打着死马当活马医的态度做这题,结果竟然还一次就A了

    【思路】

    数组f[i]表示第i个数含有哪些物质(二进制表示),然后暴力搜索;

    有个叫大米兔的大佬还提出了更强的解法,就是用线性基,优化了很多啊

     1 #include<cstdio>
     2 #include<cmath>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<iostream>
     6 #include<cstdlib>
     7 #define maxn 55
     8 #define ll long long 
     9 using namespace std;
    10 
    11 ll f[maxn];
    12 ll goal,n,m;
    13 int vis[maxn],y[maxn],tr=0;
    14 
    15 int read(){
    16     int xx=0,ff=1;char ch=getchar();
    17     while(ch<'0'||ch>'9'){if(ch=='-')ff=-1;ch=getchar();}
    18     while(ch>='0'&&ch<='9'){xx=xx*10+ch-'0';ch=getchar();}
    19     return xx*ff;
    20 }
    21 
    22 void dfs(int pos,ll now){
    23     if(tr==1)return;
    24     if(now==goal){printf("Possible
    ");tr=1;return ;}
    25     if(pos==n+1)return;
    26     if(!vis[pos]){
    27         vis[pos]=1;dfs(pos+1,now^f[pos]);vis[pos]=0;
    28     }
    29     if(tr==1)return;
    30     dfs(pos+1,now);
    31 }
    32 
    33 int main(){
    34     freopen("medicine.in","r",stdin);
    35     freopen("medicine.out","w",stdout);
    36     while(~scanf("%lld%lld",&n,&m)){
    37         goal=0;memset(f,0,sizeof(f));tr=0;
    38         memset(vis,0,sizeof(vis));
    39         memset(y,0,sizeof(y));
    40         for(int i=1;i<=m;i++){
    41             int a;a=read();y[a]++;
    42             goal^=1ll<<(a-1);
    43         }
    44         for(int i=1;i<=n;i++){
    45             int k;k=read();
    46             for(int j=1;j<=k;j++){
    47                 int a;a=read();
    48                 if(y[a])f[i]^=1ll<<(a-1);
    49             }
    50         }dfs(1,0);
    51         if(!tr)printf("Impossible
    ");
    52     }
    53 }    
    View Code

    我dfs打的丑不要笑,主要是习惯了以dep为参数的dfs,这次以pos的还有点不熟悉QAQ

  • 相关阅读:
    如何判断栈的增长方向
    时间复杂度
    shell基础part3
    shell基础part2
    shell基础part2
    linux基础part5
    linux基础part4
    linux基础part3
    linux基础part2
    shell基础part1
  • 原文地址:https://www.cnblogs.com/Danzel-Aria233/p/7782355.html
Copyright © 2011-2022 走看看