2594 解药还是毒药

题目描述 Description

Smart研制出对付各种症状的解药,可是他一个不小心,每种药都小小地配错了一点原料,所以这些药都有可能在治愈某些病症的同时又使人患上某些别的病症(你可能会问那…那是解药还是毒药啊?)……,经过Smart的努力,终于弄清了每种药的具体性能,他会把每种药能治愈的病症和能使人患上的病症列一张清单给你,然后你要根据这张清单找出能治愈所有病症的最少药剂组合……顺便说一声,病症的数目不超过10种,而且他的药是用不完的,就是说每种药剂都可以被重复使用。

输入描述 Input Description

给你们的单子里第一行是病症的总数n(1≤n≤10)。第二行是药剂的种类m(0<m≤100)。

以下有m行,每行有n个数字用空格隔开,文件的第i+2行的n个数字中,如果第j个数为1,就表示第i种药可以治愈病症j(如果患有这种病的话则治愈,没有这种病则无影响),如果为0表示无影响,如果为-1表示反而能使人得上这种病(无病患上,有病无影响)。Smart制的药任何两种性能都不同。

输出描述 Output Description

你只要输出用的最少的药剂数就可以了,其实还有可能用尽了所有的药也不能将所有病治愈,那样的话你们只要输出“The patient will be dead.”就可以了。

样例输入 Sample Input

3

2

1 0 1

-1 1 0

样例输出 Sample Output

2

数据范围及提示 Data Size & Hint

1≤n≤10

0<m≤100

本题可以转化为最短路问题

我们设第i种病没治愈为1,治愈了为0。例:二进制状态100表示第1种症状被治愈了,第2、3种症状没被治愈,转化为十进制为4。

初始状态为二进制状态下的n个1,转化为十进制为2^n-1,目标状态为0。把由初始状态到达目标状态所经历的所有状态看做一个个点,所有边的边权为1。

那么题目转化为:从状态2^n-1到状态0的最短路径。

基本算法:SPFA

解题所需自定义函数:十进制与二进制的转换

十进制转二进制:

以10为例:

10%2=0,10/2=5;

5%2=1,5/2=2;

2%2=,2/2=1;

1%2=1,1/2=0;结束

所以为1010

二进制转十进制:

以1010为例:

等于0*2^0 + 1*2^1 + 0*2^2 + 1*2^3=10

#include<cstdio>
#include<iostream>
#include<cmath>
using namespace std;
int n,m;
int head=,tail=;//我用的是左闭右开区间,即区间范围为[head,tail-1]
int l[];//二进制状态存储数组
int a[][];//a[i][j]表示第i种药剂对症状j的疗效
bool t[];//十进制判重数组
struct node
{
int w,sum;//w当前状态,十进制,sum达到状态w所需的药剂数
};
node q[];//队列
node now;
int change(int s)
{
if(!s) return ;
return l[s]+change(s-)*;
}
int work(int d,int g)//d:第d种药剂,g:使用d药剂之前的状态,十进制
{
for(int i=n;i;i--)//将十进制g转化为二进制,并一位一位的存在l数组中
{
l[i]=g%;
g/=;
}
for(int i=;i<=n;i++)//第d种药剂对状态的修改
{
if(a[d][i]==) l[i]=;
else if(a[d][i]==-) l[i]=;
}
int er=change(n);//因为l数组中的数是一位一位存的,这一句要把l[]数组中的数合起来。例:l[1]=1,l[2]=0;er=10
int k=,u=;//二进制er转为十进制k
while(er)
{
int y=er%;
k+=y*pow(,u);
u++;
er/=;
}
return k;
}
void push(node cur)
{
q[tail++]=cur;
}
void pop()
{
head++;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<=m;i++)
for(int j=;j<=n;j++)
scanf("%d",&a[i][j]);
q[tail].w=pow(,n)-;//初始状态n个1所代表的二进制数,转化为十进制为2^n-1
q[tail].sum=;//初始没用任何药剂
t[q[].w]=true;
tail++;//入队,队尾指针后移
while(head<tail)//队列不为空
{
for(int i=;i<=m;i++)//枚举每一种药剂
{
now=q[head];//取出队首
int h=work(i,now.w);//在用第i种药剂之前,状态为now.w,用了第i种药剂之后,状态为h
if(!h)//目标状态(治愈)
{
printf("%d",now.sum+);//因为now存的值是使用药剂i之前的值,而h更新是使用了药剂i之后,所以要+1
return ;
}
if(!t[h])//不是目标状态且状态h在之前没有出现过。因为spfa实质是宽搜,如果状态h在之前出现过,它在之前已经入队
{
now.sum++;//药剂数+1
now.w=h;//状态转移
push(now);//入队
t[h]=true; //状态h标记为已出现过
}
}
pop();//队首出队
}
printf("The patient will be dead.");//若队列中没有状态了,但还没有结束程序,则无药可治
}

codevs 2594 解药还是毒药的更多相关文章

  1. 解药还是毒药(codevs 2594)

    2594 解药还是毒药  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond 题解  查看运行结果     题目描述 Description Smart研制出对 ...

  2. codevs2594解药还是毒药(状压dp)

    2594 解药还是毒药  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond     题目描述 Description Smart研制出对付各种症状的解药,可是 ...

  3. 【BFS】【位运算】解药还是毒药

    [codevs2594]解药还是毒药 Description Smart研制出对付各种症状的解药,可是他一个不小心,每种药都小小地配错了一点原料,所以这些药都有可能在治愈某些病症的同时又使人患上某些别 ...

  4. Hash_P1026毒药?解药?

    #include <iostream> #include <cstdio> #include <algorithm> #include <cstring> ...

  5. 补丁vs错误(codevs 2218 错误答案)

    题目描述 Description 错误就是人们所说的Bug.用户在使用软件时总是希望其错误越少越好,最好是没有错误的.但是推出一个没有错误的软件几乎不可能,所以很多软件公司都在疯狂地发放补丁(有时这种 ...

  6. NOI2018准备Day12

    上午学了1个小时左右的指针,学了个从句子中分离单词的方法,其他的感觉没学到啥. 中午看了一会儿网络流,懵逼...... A了8道题,4道钻石.3道黄金.1道白银,自己写出了codevs"解药 ...

  7. java web 程序---猜数字游戏的猜了多少次的代码

    思路:用setAttribute()放 ,然后直接输出 Integer str=(Integer)session.getAttribute("count"); int num3= ...

  8. vijosP1026毒药?解药?

    hash. 怎么感觉叫状态压缩bfs比较合适呢? #include<cstdio> #include<algorithm> #include<cstring> us ...

  9. Tyvj3308毒药解药题解

    题目大意 这些药都有可能在治愈某些病症的同一时候又使人患上某些别的病症--经过我天才的努力.最终弄清了每种药的详细性能,我会把每种药能治的病症和能使人患上的病症列一张清单给你们,然后你们要依据这张清单 ...

随机推荐

  1. python征程1.3(初识python)

    1.字典. 字典是python中的映射的数据类型,由键值对构成,几乎所有类型的python对象都可以用作键,不过一般还是以数字或是字符串最为常见.值可以是任意类型的python对象,字典元素用{}来包 ...

  2. 使用HBaseShellPro操作Hadoop 2系列发行版CDH4.4

    前言 对于hadoop,hbase由于项目紧张原因好几个月没有时间认真的来总结下了,最近有一些空,就来继续的把项目中用到的一些技术实际的写出来,动动手,好久没有写东西了,都生疏了,说起hadoop,公 ...

  3. jQuery带tab切换搜索框样式代码

    效果体验:http://hovertree.com/texiao/jquery/23/ 代码如下,保存到HTML文件也可以查看效果: <!DOCTYPE html> <html la ...

  4. php文件之间传值的三种主流并且常用的方式

    一.表单传值 在<form>中的action填入要跳转页面的路径,method填入POST或者GET方法.表单中的提交按钮按下后,就会把<form>中有value都传到要跳转的 ...

  5. iOS NSArray数组过滤

    需求:在一个数组里面,将在这个数组中的并且在另一个数组里面的元素过滤掉. 即:在一个数组dataArray里面,将在dataArray数组中的并且在filteredArray数组里面的元素过滤掉. / ...

  6. SharePoint 2013 自定义扩展菜单

    在对SharePoint进行开发或者功能扩展的时候,经常需要对一些默认的菜单进行扩展,以使我们开发的东西更适合SharePoint本身的样式.SharePoint的各种功能菜单,像网站设置.Ribbo ...

  7. LINUX下C-C++类软件的诊断

    一般C/C++写程序由于内存.指针等问题在后期的过程都一般会遇到内存等资源泄露.崩溃等问题,对于这些问题,一般从哪个角度解决呢? 下面从几个角度进行总结: 内存泄露 首先需要注意一个问题是top或者h ...

  8. Java中 实现多线程成的三种方式(继承,实现,匿名内部类)

    ---------------------------------------------------------------------------------------------------- ...

  9. iOS开发之功能模块--用runtime给UIView类别拓展PressMenu工具

    这是个很有用的列别工具类,在聊天对话框添加和QQ一样的"复制.粘贴.取消"等选项,而且使用起来很方便,只要找到聊天泡泡内部的某个View,比如Label或者背景冒泡的UIImage ...

  10. OAuth2.0 四种授权模式

    OAuth2.0简单笔记(四种授权模式) 金天:坚持写东西,不是一件容易的事,换句话说其实坚持本身都不是一件容易的事.如果学习有捷径,那就是不断实践,不断积累.写笔记,其实是给自己看的,是体现积累的一 ...