HDU4451

HDU4451 Dressing

王鹏有N件衣服,M件裤子,K双靴子,所以理论上他有N*M*K种搭配方式。但是他的妈妈不喜欢王鹏德一些衣服—裤子或者裤子—鞋子的搭配。所以现在要你求王鹏到底有多少种搭配方式。

输入:输入包含多个实例。第一行是N,M,K三个数。(1≤N,M,K≤1000)。第二行包含一个整数P(0≤P≤2000000),表有多少对不合适。以下P行分别为“clothes x pants y” or “pants y shoes z”.表示第x个衣服与第y个裤子不合适(1≤x≤N,1 ≤y≤M) 或者 第y个裤子与第z个鞋子不合适(1≤y≤M,1≤z≤K)。输入以0 0 0表示结束。

输出:合适搭配的总数。

分析:

本题其实就是容斥原理加枚举。

解法一:此解法注意不要有遗漏的情况!

设总数为S=N*M*K,冲突1类“clothes x pants y”的个数为A,冲突2类“pants y shoes z”的个数为B个。

则合适搭配的总数为:S-A*K-B*N+O.其中O是A与B重叠的个数。如clothes 1 pants 2与pants 2shoes 5 重叠的O值为1,指的是情况

clothes 1 pants 2 shoes 5。

注意pants 2 shoes 5pants 2shoes 6可以共存的。其实裤子k可以分别与鞋子1,2,3,4,5,6都冲突。

其实这道题目就是容斥原理加枚举的运用。

AC代码:

#include<cstdio>
#include<cstring>
using namespace std;
int a[200+1000],b[200+1000];//a[i]=j,表示i裤子与j衣服冲突,b[i]=j表i裤子与j鞋子冲突。
int main()
{
   //freopen("in.txt","r",stdin);
   //freopen("out.txt","w",stdout);
    int n,m,k;
   while(scanf("%d%d%d",&n,&m,&k)==3)//衣服,裤子,鞋子数目
    {
       if(n==0&&m==0&&k==0)break;
       memset(a,0,sizeof(a));
       memset(b,0,sizeof(b));
        int p;
        intsum=0;//合适的搭配总数
        char s1[100],s2[100];
        int x,y;
        intA=0,B=0;//A表衣服-裤子冲突总数,B表裤子-鞋子冲突总数
        intO=0;//A与B中多删除了一次重叠的个数
       scanf("%d",&p);
       while(p--)
        {
           scanf("%s%d%s%d",s1,&x,s2,&y);
           if(strcmp(s1,"clothes")==0)
            {
               A++;
               a[y]++;
            }
            elseif(strcmp(s1,"pants")==0)
            {
               b[x]++;
               B++;
            }
        }
        for(inti=1; i<=m; i++)
        {
            if(a[i]!=0)
               O+=a[i]*b[i];//鞋子i所产生的重叠的个数
        }
        sum =n*m*k-A*k-B*n+O;
       printf("%d\n",sum);
    }
    return 0;
}

解法二:

其实合适搭配总数为:各个鞋子的sum值之和。

Sum[i]表示第i个鞋子合适搭配的数目=可以与i搭配的衣服数*可以与i搭配的鞋子数。

AC代码:

#include<cstdio>
#include<cstring>
using namespace std;
int a[200+1000],b[200+1000];//a[i]=j,表示i裤子与j衣服冲突,b[i]=j表i裤子与j鞋子冲突。
int main()
{
   //freopen("in.txt","r",stdin);
   //freopen("out.txt","w",stdout);
    int n,m,k;
   while(scanf("%d%d%d",&n,&m,&k)==3)
    {
       if(n==0&&m==0&&k==0)break;
       memset(a,0,sizeof(a));
       memset(b,0,sizeof(b));
        int p;
        intsum=0;
        chars1[100],s2[100];
        int x,y;
        intA=0,B=0;
        int O=0;
       scanf("%d",&p);
       while(p--)
        {
           scanf("%s%d%s%d",s1,&x,s2,&y);
           if(strcmp(s1,"clothes")==0)
            {
               A++;
               a[y]++;
            }
            elseif(strcmp(s1,"pants")==0)
            {
               b[x]++;
               B++;
            }
        }
        for(inti=1; i<=m; i++)
        {
           //if(a[i]!=0)
              // O+=a[i]*b[i];
            sum+= (n-a[i])*(k-b[i]);
           //printf("O is : %d\n",O);
        }
        //sum =n*m*k-A*k-B*n+O;
       printf("%d\n",sum);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值