解药还是毒药
时间限制: 1 s
空间限制: 128000 KB
题目描述Description
Smart研制出对付各种症状的解药,可是他一个不小心,每种药都小小地配错了一点原料,所以这些药都有可能在治愈某些病症的同时又使人患上某些别的病症(你可能会问那…那是解药还是毒药啊?)……,经过Smart的努力,终于弄清了每种药的具体性能,他会把每种药能治愈的病症和能使人患上的病症列一张清单给你,然后你要根据这张清单找出能治愈所有病症的最少药剂组合……顺便说一声,病症的数目不超过10种,而且他的药是用不完的,就是说每种药剂都可以被重复使用。
给你们的单子里第一行是病症的总数n(1≤n≤10)。第二行是药剂的种类m(0<m≤100)。
以下有m行,每行有n个数字用空格隔开,文件的第i+2行的n个数字中,如果第j个数为1,就表示第i种药可以治愈病症j(如果患有这种病的话则治愈,没有这种病则无影响),如果为0表示无影响,如果为-1表示反而能使人得上这种病(无病患上,有病无影响)。Smart制的药任何两种性能都不同。
你只要输出用的最少的药剂数就可以了,其实还有可能用尽了所有的药也不能将所有病治愈,那样的话你们只要输出“The patient will be dead.”就可以了。
3
2
1 0 1
-1 1 0
2
数据范围及提示Data Size & Hint
1≤n≤10
0<m≤100
采用状态压缩的方式进行搜索
因为每个病症只有两种状态 患or不患
用一个01字符串来存储这种状态
剪枝:如果这种状态存在就不入队
如果得到最终解直接退出
code:
var i,j,k:longint;
dui:array[1..1024]of string;
init:array[1..100,1..10]of longint;
deep:array[1..1024]of longint;
n,m:longint;
ok:boolean;
head,tail:longint;
temp:string;
pear:boolean;
function pan(x:string):boolean;
var i:longint;
begin pan:=true;
for i:=1 to n do
if x[i]=‘1‘
then exit(false);
exit(true);
end;
begin
readln(n,m);
for i:=1 to m do
for j:=1 to n do
read(init[i,j]);
ok:=false;
head:=1; tail:=1;
deep[1]:=0;
dui[1]:=‘‘;
for i:=1 to n do
dui[1]:=dui[1]+‘1‘;
while (head<=tail)and(not ok) do
begin for i:=1 to m do
begin pear:=false;
temp:=dui[head];
for j:=1 to n do
begin if init[i,j]=1 then temp[j]:=‘0‘;
if init[i,j]=-1 then temp[j]:=‘1‘;
end;
for j:=1 to tail do
if temp=dui[j]
then pear:=true;
if not pear
then begin inc(tail);
dui[tail]:=temp;
deep[tail]:=deep [head]+1;
if pan(temp)
then begin writeln(deep[tail]);
halt;
end;
end;
end;
inc(head);
end;
writeln(‘The patient will be dead.‘);
end.
原文:http://www.cnblogs.com/spiderKK/p/4928522.html