Gym

来源:互联网 发布:杀师案 知乎 编辑:程序博客网 时间:2024/06/15 04:03

题意

从前菜,主菜,点心中各选一道菜,每道菜由一些原料组成,每种原料有一些不同的品种,问总共有多少种方法组成这三道菜。如果多道菜使用了相同的原料,则这些菜中的这种原料将是相同品种的,另外有一些不可以组合在一起的菜。

思路

枚举所有可能组合,统计该组合使用不同原料的数目,将原料品种数相乘即为该组合方案数。相乘前先要用除法判断是否超过1e18

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <set>using namespace std;typedef long long LL;LL inf=1e18;bool vis[1005];LL ci[1005];LL ing[105][30];bool G[105][105];set<LL> S;int r,s,m,d,n;int main(){    while(~scanf("%d%d%d%d%d",&r,&s,&m,&d,&n)){        memset(G,0,sizeof(G));        bool fl=1;        LL ans=0;        for(int i=1;i<=r;++i)scanf("%I64d",&ci[i]);        for(int i=1;i<=s+m+d;++i){            scanf("%I64d",&ing[i][0]);            for(int j=1;j<=ing[i][0];++j){                scanf("%I64d",&ing[i][j]);            }        }        int a,b;        for(int i=0;i<n;++i){            scanf("%d%d",&a,&b);            G[min(a,b)][max(a,b)]=1;        }        for(int i=1;i<=s;++i){            for(int j=s+1;j<=s+m;++j){                for(int k=s+m+1;k<=s+m+d;++k){                    if(!G[i][j]&&!G[i][k]&&!G[j][k]){                        if(!fl)break;                        S.clear();                        for(int x=1;x<=ing[i][0];++x)S.insert(ing[i][x]);                        for(int x=1;x<=ing[j][0];++x)S.insert(ing[j][x]);                        for(int x=1;x<=ing[k][0];++x)S.insert(ing[k][x]);                        LL cur=1;                        for(set<LL>::iterator si=S.begin();si!=S.end();++si){                            if(cur>inf/ci[*si]){fl=0;break;}                            cur*=(ci[*si]);                        }                        ans+=cur;                        if(ans>inf)fl=0;                    }                }            }        }        if(fl)printf("%I64d\n",ans);        else printf("too many\n");    }    return 0;}
原创粉丝点击