問題の意味:ピザを注文、ピザが「P」16のトッピングに「A」を持って、あなたは友人の数を持っているそれぞれの友人は、要件の数、形、「+ A-B + EP」の文字列を、持っていますA(ファイサクラメントに友達リクエストは、Eは、B、当然のP.せずに、あなただけのピザを注文する必要があるので、ピザは、各友人のすべての要件を満たすことができない、少なくとも一つの要件は、それぞれの友人もでき満たしていることを示しています彼らは質問のピザの意味を満たすために注文することができた場合、出力「トッピングを:」何人かの友人は、Bが好きではない、ファイサリーなしBは、TAの要件を満たすと考えることはできない);、ファイサリーような友人は、TAの要件を満たすために考えられていることがあります。その後、複数のソリューションがある場合(、出力辞書順最小の(もちろん、出力の成分を追加していないものを示すために、何もすることはできません)「CELP」のような形、ピザ成分の出力を向上させる大規模なため、小規模から同じライン辞書に従ってくださいプログラム)あなたは、出力ライン「いいえピザは、これらの要求を満たすことはできません。」メモのタイトルの意味を満たすためにピザを注文することができない場合:「」複数のデータセットのタイトルは、各データが別々のラインエンドとして表現。
分析:わずか16成分、それは各リクエストセットに進数として見られている。\(F [i]は[0/1] \) i番目を表す成分を追加して構成し、別々に添加される成分を必要としません列挙するバイナリ各ストリングの数(整数格納されているINT)まず、その第1のプリアウトFアレイ、及び大(辞書式に最小の法的保証プログラム)に次いで小さな0。\(2 ^ {15} - 1 \)あなたが合法的にできるかどうかを判断します。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#define ll long long
using namespace std;
inline int read(){
int x=0,o=1;char ch=getchar();
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')o=-1,ch=getchar();
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*o;
}
const int N=(1<<16)-1;
int n,bj,f[1005][2];
char ch[1005];
inline void add(char ch[]){
int len=strlen(ch);
for(int i=0;i<len-1;++i){
if(ch[i]=='+')f[n][1]+=1<<(ch[++i]-'A');
else f[n][0]+=1<<(ch[++i]-'A');
}
}
inline bool pd(int x){
for(int i=0;i<n;++i)
if((x&f[i][1])||((x^N)&(f[i][0])))continue;
else return false;
return true;
}
int main(){
while(~(scanf("%s",ch))){
if(ch[0]!='.'){
add(ch);++n;
continue;
}
for(int i=0;i<=N;++i)
if(pd(i)){
bj=1;n=i;
break;
}
if(bj){
printf("Toppings: ");
for(int i=0;i<=15;++i)
if(n&(1<<i))printf("%c",i+'A');
printf("\n");
}
else printf("No pizza can satisfy these requests.\n");
n=0;bj=0;memset(f,0,sizeof(f));
}
return 0;
}