题目:uva 565 - Pizza Anyone?(暴力枚举 + 二进制)
题目大意:题目是说有一个人要帮他的朋友们定批萨,然后每个朋友都有自己的口味要求,问能不能定一个批萨然后满足每个朋友的至少一个要求。
能就输出所定批萨里面加的东西,,输出要求按字典序;
不能就输出:No pizza can satisfy these requests.
解题思路:这题里面有16种材料,每种材料只有取与不取的可能,这样就有 2^16 种( 0 - 2^16 - 1),枚举出每种情况然后在分别看是否能满足每个朋友的至少的一个要求,可以就输出。不用再往后找了。但是这题的数据量不是很小,65535 * 100 (t) * 12 = 78642000,但是这种状况毕竟很少很极端,但是这样时间也很紧迫,所以可以用二进制来优化一下时间。
代码:
#include <stdio.h>
#include <string.h>
const int N = 100;
const int M = 16;
char str[M * 2];
int t;
int result[M];
bool flag;
struct TOPPING {
char need[M];//需要的
char omit[M];//不要的
int cnt1, cnt2;//前面两个数组内元素的个数
} topping[N];
void init () {
t = flag = 0;
memset (topping, 0, sizeof (topping));
}
//把每个字符串分解出需要和不需要的东西
void handle () {
for (int i = 0; i < strlen (str); i++) {
if (str[i] == '+') {
topping[t].need[topping[t].cnt1++] = str[i + 1];
i ++;
} else if (str[i] == '-') {
topping[t].omit[topping[t].cnt2++] = str[i + 1];
i ++;
}
}
t++;
}
//判断result当前情况下是否可以满足每个朋友的至少一个请求
bool judge() {
bool tag;
for (int j = 0; j < t; j++) {
tag = 0;
for (int k = 0; k < topping[j].cnt2; k++)
if (result[topping[j].omit[k] - 'A'] == 0) {
tag = 1;
break;
}
if (tag)
continue;
for (int k = 0; k < topping[j].cnt1; k++)
if (result[topping[j].need[k] - 'A'] == 1) {
tag = 1;
break;
}
if (!tag)
return false;
}
return true;
}
//将每个十进值数所对应的二进制数表示为材料的取否
void solve (int n) {
int pos = 0;
while (pos < M) {
result[pos++] = n & 1;
n >>= 1;
}
if (judge())
flag = 1;
}
int main () {
while (scanf ("%s", str) != EOF) {
init ();
while (str[0] != '.') {
handle ();
scanf ("%s", str);
}
int m = 1<<17 - 1;
int n = 0;
// printf ("%d\n", m);
while (n < m) {
solve (n);
if (flag)
break;
n++;
}
if (!flag)
printf ("No pizza can satisfy these requests.\n");
else {
printf ("Toppings: ");
for (int i = 0; i < M; i++)
if (result[i])
printf ("%c", i + 'A');
printf("\n");
}
}
return 0;
}