Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1526190
  • 博文数量: 399
  • 博客积分: 8508
  • 博客等级: 中将
  • 技术积分: 5302
  • 用 户 组: 普通用户
  • 注册时间: 2009-10-14 09:28
个人简介

能力强的人善于解决问题,有智慧的人善于绕过问题。 区别很微妙,小心谨慎做后者。

文章分类

全部博文(399)

文章存档

2018年(3)

2017年(1)

2016年(1)

2015年(69)

2013年(14)

2012年(17)

2011年(12)

2010年(189)

2009年(93)

分类: LINUX

2009-11-24 19:01:31

你准备为你和朋友订一个比萨,他们告诉你每个人希望比萨里有什么和没有什么材料。当然,他们也明白只有一个比萨,所以没有人期望他所以的要求都得到满足。你订一个比萨满足他们每个人至少一项的要求吗?
比萨店提供的比萨口味如下,你可以在一个比萨中要或者不要当中的任何一项:
代码
口味
A
凤尾鱼
B
黑橄榄
C
加拿大熏肉
D
方丁大蒜
E
浓奶酪
F
鲜花椰菜
G
青辣椒
H
火腿
I
意大利香肠
J
加拉佩诺胡椒
K
波兰熏肠
L
瘦牛肉
M
蘑菇
N
脱脂羊乳酪
O
洋葱
P
胡椒
 
你的朋友给你一行文字描述他们的比萨口味。例如:
+O-H+P;
意味这某位朋友将接受一个包含洋葱,或不包含火腿,或带有胡椒的比萨。而
-E-I-D+A+J;
表示某位朋友将接受一个不包含浓奶酪或意大利香肠或方丁大蒜的,或带有凤尾鱼或加拉佩诺胡椒的比萨。
输入格式:
每个要求一行,并以分号结束。直到“.”表示所有约束都已输入结束。
输出格式:
如果存在可分配的方案则先输出一个长度为10 的字符串“Toppings: ”,紧接输出分配方案(按字母顺序由小到大)。
如果不存在可分配的方案则输出:“No pizza can satisfy these requests.”
输入输出样例:
Simple input 1
Output for the input
+A+B+C+D-E-F-G-H;
-A-B+C+D-E-F+G+H;
-A+B-C+D-E+F-G+H;
.
Toppings:
 
Simple input 2
Output for the input
+A+B+C+D;
+E+F+F+H;
+A+B-G;
+O+J-F;
+H+I+C;
+P;
+O+M+L;
+M-L+P;
.
 
Toppings: CELP
 
Simple input 3
Output for the input
+A;
-A;
.
 
No pizza can satisfy these requests.
 
解:
本题有两种解法:第一种比较复杂:首先将每个人的口味约束表示乘析取式,如+A -B+C表示成(A | !b | C),接着将所有人的口味表示成合取式,如+A+B和+C -D表示成( A | B ) & (C | !D),在将合取式中所有的括号展开变成析取式,这时使任意析取式为真的表达式都是问题的解,如(A & B)| (C &!D) 表示当A、B同时取真,或者C取真D取假时都是问题的解。
第二种方法是使用搜索算法,穷举所有的可能性,直到找到解为止。
尽管这种方法没有第一种那么聪明,但是由于实现起来比第一种简单的多,所以在这里采用搜索算法更科学些。
使用搜索算法时还要注意的两个问题是:1、比萨约束的存储方式;2、如何判断比萨是否符合要求。
这里使用位运算来表示比萨的约束方式:定义一个整形数组want[ PERSONMAX],其中PERSONMAX表示朋友的个数,want[ i ]表示第i 为朋友想要的口味,例如:
want[ i ]=00000000000000000000000001000011 表示第i个朋友想要口味凤尾鱼、黑橄榄和青辣椒。注意由于整形有32位而pizza的口味只有16种,所以这里高16为无效。
同理,定义另一个整形数组hate[PERSONMAX],hate[i]表示第i位朋友不想要的口味,例如:
hate[ i ]=00000000000000000000000000001100 表示第i个朋友不想要的口味有:方丁大蒜和加拿大熏肉。
于是在表述pizza是否符合某人的口味是只要进行如下判断:
(pizza & want[ i ] >0) ||(!pizza & hate[ i ] >0)
这种表示方法充分利用了位运算的优点,使得程序的处理十分的方便,而且节省了空间.
 
代码:
 
 
#include<stdio.h>
#include
<string.h>
#include
<stdlib.h>
#include
<fcntl.h>
#include
<io.h>


#define TYPELEN 16    //比萨口味的种类数
#define PERSONMAX 30 //最多的朋友人数

int pizza,want[PERSONMAX],hate[PERSONMAX],person;
char buf[TYPELEN*2];

void
setup()
{
    
int count,i;
    count
=strlen(buf)-1;    //最后一个是分号,因舍去。
    memset(want+person,0,TYPELEN);    
    memset(hate
+person,0,TYPELEN);
    
for(i=1;i<count;i+=2)
        
if(buf[i-1]=='+')
            want[person]
=want[person]|(1<<(buf[i]-65));
        
else
            hate[person]
=hate[person]|(1<<(buf[i]-65));
    
++person;
}


bool 
checkPizza()
{
    
bool flag;
    
int i;
    
for(pizza=0;pizza<65536;pizza++){    //搜索所有的可能pizza取值,直到成功
        flag=true;
        
for(i=0;i<person;i++)
            
if(!((pizza&want[i])>0 || (!pizza&hate[i])>0)){
                flag
=false;
                
break;
            }

        
if(flag) return true;
    }

    
return false;
}

void
output(){
 int i;
 printf("Toppings: ");
 for(i=0;i  if(pizza&(1< puts("\0");
}

void
main(){
 person=0;
 while(1){
  scanf("%s",buf);
  if(buf[0]=='.') break;
  setup();
 }
 if(checkPizza()==true) output();
 else puts("No pizza can satisfy these requests."); 
}
阅读(1097) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~