[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\n");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\n");
52     }
53 }    

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

时间: 2024-08-13 22:28:50

[noip模拟]食物中毒<暴搜+状压优化>的相关文章

[CSP-S模拟测试]:巨神兵(状压DP)

题目描述 欧贝利斯克的巨神兵很喜欢有向图,有一天他找到了一张$n$个点$m$条边的有向图.欧贝利斯克认为一个没有环的有向图是优美的,请问这张图有多少个子图(即选定一个边集)是优美的?答案对$1,000,000,007$取模. 输入格式 第一行两个整数$n$和$m$.接下来$m$行每行两个整数表示一条有向边.保证无重边无自环. 输出格式 一行一个整数表示答案,对$1,000,000,007$取模. 样例 样例输入: 3 61 22 11 33 12 33 2 样例输出: 25 数据范围与提示 对于

Luogu2040 | 打开所有的灯 (广搜+状压)

题目背景 pmshz在玩一个益(ruo)智(zhi)的小游戏,目的是打开九盏灯所有的灯,这样的游戏难倒了pmshz... 题目描述 这个灯很奇(fan)怪(ren),点一下就会将这个灯和其周围四盏灯的开关状态全部改变.现在你的任务就是就是告诉pmshz要全部打开这些灯. 例如: 0 1 1 1 0 0 1 0 1 点一下最中间的灯 \([2,2]\) 就变成了 0 0 1 0 1 1 1 1 1 再点一下左上角的灯 \([1,1]\) 就变成了 1 1 1 1 1 1 1 1 1 达成目标.最少

【NOIP2016提高组】愤怒的小鸟(状压宽搜)

题目描述 Kiana最近沉迷于一款神奇的游戏无法自拔. 简单来说,这款游戏是在一个平面上进行的. 有一架弹弓位于(0,0)处,每次Kiana可以用它向第一象限发射一只红色的小鸟,小鸟们的飞行轨迹均为形如的曲线,其中a,b是Kiana指定的参数,且必须满足a<0. 当小鸟落回地面(即x轴)时,它就会瞬间消失. 在游戏的某个关卡里,平面的第一象限中有n只绿色的小猪,其中第i只小猪所在的坐标为(xi,yi). 如果某只小鸟的飞行轨迹经过了(xi,yi),那么第i只小猪就会被消灭掉,同时小鸟将会沿着原先

NOJ 1116 哈罗哈的大披萨 【淡蓝】 [状压dp+各种优化]

我只能说,珍爱生命,远离卡常数的题...感谢陈老师和蔡神,没有他们,,,我调一个星期都弄不出来,,,, 哈罗哈的大披萨 [淡蓝] 时间限制(普通/Java) : 1000 MS/ 3000 MS          运行内存限制 : 65536 KByte总提交 : 73            测试通过 : 9 描述 热风哈罗哈(三牌楼)店正在搞活动:他们将提供一个大披萨给第一个告诉他们以下信息的人:一次购买任一种披萨,哪种单位面积的价格最低.问题初步想一想,好像是这么解决:“对于每个披萨计算平均

ZOJ1100 状压DP +深搜

记得做过类似于这类题目是可以用组合数学方法来解决的,可惜淡忘了,也找不到了,看了网上的也有人提到过可以用组合公式解决,可是没人做,都是用了状压DP的方法,这个状压很难讲清楚吧,推荐两篇 第一遍大体看看这个:http://blog.csdn.net/crux_d/article/details/2206736 想要具体实现的时候看看他的解析:http://blog.csdn.net/yan_____/article/details/8719748 #include<iostream> #incl

Codeforces 327E Axis Walking (状压dp lowbit优化)

E. Axis Walking time limit per test:3 seconds memory limit per test:512 megabytes Iahub wants to meet his girlfriend Iahubina. They both live in Ox axis (the horizontal axis). Iahub lives at point 0 and Iahubina at point d. Iahub has n positive integ

【bzoj1097】[POI2007]旅游景点atr 状压dp+堆优化Dijkstra

题目描述 FGD想从成都去上海旅游.在旅途中他希望经过一些城市并在那里欣赏风景,品尝风味小吃或者做其他的有趣的事情.经过这些城市的顺序不是完全随意的,比如说FGD不希望在刚吃过一顿大餐之后立刻去下一个城市登山,而是希望去另外什么地方喝下午茶.幸运的是,FGD的旅程不是既定的,他可以在某些旅行方案之间进行选择.由于FGD非常讨厌乘车的颠簸,他希望在满足他的要求的情况下,旅行的距离尽量短,这样他就有足够的精力来欣赏风景或者是泡MM了^_^.整个城市交通网络包含N个城市以及城市与城市之间的双向道路M条

HDU 4284 状压dp+spfa堆优化

题意: 给定n个点 m条无向边 d元. 下面m行表示每条边 u<=>v 以及花费 w 下面top 下面top行 num c d 表示点标为num的城市 工资为c 健康证价格为d 目标是经过给定的top个城市,当到达该城市时,必须马上购买该城市的健康证并打工赚钱(每个城市只打工1次) 问从1城市出发,最后回到1城市,能否收集到所有的健康证 思路: 由于top很小,所以状压dp dp[i][tmp]表示当前处于i点 经过城市的状态为tmp时 身上最多的钱. 首先对dis数组floyd 跑出最短路,

POJ 1185 炮兵阵地 状压DP+离散化优化

一开始能想到的状态就只有位压两行和当前行的行号,这样无论是空间和时间都是无法接受的. 但是因为炮兵的攻击范围比较大,而且又有地形限制,每一行的状态其实不多了,打表看了一下不超过80种,离散化一下就可以随意DP了. 据说题目也可以抽象成二分图最大匹配来搞?感觉复杂度有点高 #include <cstdio> #include <cstring> #include <iostream> #include <map> #include <set> #i