http://codeforces.com/contest/1042/problem/B
题意:
给出n种饮料,每种饮料还有一种或多种维生素(A或B或C),某人想集齐三种维生素,问最少需要花费多少?
每一行先输入每种饮料的价格,再输入每种饮料的包含的维生素种类。
将ABC分别用一个数字表示,开始时准备:1表示A,2表示B,3表示C。
包含维生素A的饮料=1,包含维生素B的=2,C=3,AB=A+B=3,到了这就发现这样不对,有重复了。
所以我们最好用三个质数表示ABC。
这里A=2,B=5,C=11。
AB=A*B=10,AC=A*C=22,BC=B*C=55;
ABC=110.
当然这里用加表示也可以,看心情啦。
那么我们需要在输入时,记录每种饮料的还费最小值,并且判断三种维生素是否都出现过。
那么我们的答案就是$$min { AB+C,AC+B,BC+A,A+B+C,AC+BC,AB+BC,AB+AC }$$
当然判断答案时你需要判断这种饮料是否出现过。
!!!越离奇的方法越不容易被hack。
#include <algorithm> #include <iostream> #include <cstring> #include <cstdio> #include <cmath> using namespace std; int p[100000],ans,cnt; int n,val[1006],cost,a[222]; //A=2,B=5,C=11; char s[4]; bool vis[1100],hack[100000]; //hack数组判断某种饮料是否出现过。 int main() { ans=2147483647; a['A']=2;a['B']=5;a['C']=11; memset(p,0x7f,sizeof(p)); scanf("%d",&n); for(int i=1; i<=n; i++) { scanf("%d",&cost); scanf("%s",s); int l=strlen(s),tot=1; for(int j=0; j<l; j++) { tot*=a[s[j]]; if(!vis[s[j]])vis[s[j]]=1,cnt++; } p[tot]=min(p[tot],cost); hack[tot]=1; } if(cnt<3)printf("-1"); else { if(hack[2]&&hack[5]&&hack[11])ans=min(ans,p[2]+p[5]+p[11]); if(hack[10]&&hack[11])ans=min(ans,p[10]+p[11]); if(hack[22]&&hack[5])ans=min(ans,p[22]+p[5]); if(hack[55]&&hack[2])ans=min(ans,p[55]+p[2]); if(hack[110])ans=min(ans,p[110]); if(hack[10]&&hack[55])ans=min(ans,p[10]+p[55]); if(hack[22]&&hack[55])ans=min(ans,p[22]+p[55]); if(hack[10]&&hack[22])ans=min(ans,p[10]+p[22]); printf("%d",ans); } }