题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=4451
题目描述:
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 919 Accepted Submission(s): 414
题意:有上衣 裤子 鞋子 的任意搭配,给出特定的两种搭配,问此两种搭配不能出现的所有搭配数数多少。即总搭配数 - 特定条件搭配 = 答案
题解:这里有上衣 裤子 鞋子 三个因素,不妨看成三个坐标方向,即上衣是x轴 裤子是y轴 鞋子是z轴,这样问题就抽象为,给出一个x*y*z的具体大小的三维空间,其中特定条件
为(x,y)的直线 或 (y,z)的直线,问总三维空间的点数(即x*y*z)减去 特定条件给出的直线所占的点的数量 后 剩余点的数量。而直线所占点的数量依赖于未确定
那一维的大小,如有三维空间(10,12,20) 那么直线(10,12)所占三维空间的点的数量就是20。如果特定条件给出的直线没有交点 那么来一条直线就减去它所占的
的点数,如果有交点那么就记录有多少条(x,y)的点交到(y,z)上,即来一条(y,z)就减去其x,而来一条(x,y),就记录以y为索引这样的(x,y)直线有多少条
方便后面减去重复点个数(防止多减去了点)。这样,最后遍历下记录出来的(x,y)记录集,减去有重复点(即与(y,z)有交点)的直线。即是最终答案。还是看代码
把,感觉解释的不是很清楚。
代码:
#include
#include
#include
#include
#include
#include
using namespace std;
int N=0,M=0,K=0,P=0;
char Str1[10+5],Str2[10+5];
int s1=0,s2=0;
int ys[1000+5];
int yss[1000+5];
int counts=0;
/*for test*/
int test()
{
return(0);
}
/*main process*/
int MainProc()
{
while(scanf("%d%d%d",&N,&M,&K)!=EOF&&(N>0||M>0||K>0))
{
scanf("%d",&P);
memset(yss,0,sizeof(yss));
memset(ys,0,sizeof(ys));
counts=N*M*K;
int i=0;
for(i=1;i<=P;i++)
{
scanf("%s%d%s%d",Str1,&s1,Str2,&s2);
if(Str1[0]=='c')//y is s2
{
ys[s2]++;//record the repeat point
}
else//y is s1
{
counts-=N;
yss[s1]++;
}
}
for(i=1;i<=M;i++)
{
if(ys[i]>0)
{
for(int j=1;j<=ys[i];j++)
counts-=(K-yss[i]);
}
}
printf("%d\n",counts);
}
return(0);
}
int main()
{
MainProc();
return(0);
}
ys数组记录(x,y)的直线,以y为索引。yss记录(y,z)的直线,亦即可能出现交点的个数,以y为索引。以y为索引的原因是,(x,y)直线与(y,z)直线若要存在交点,那么两者的y必须相等。
这样第一个for相当于是减去所有的(y,z)直线上的点。最后遍历ys数组是减去(x,y)直线以及与(y,z)直线有交点的直线的所占点的数量,ys[i]>0表示这里有(x,y)
直线需要减去,然后遍历ys[i]的内容表示要减去该y坐标的多条(x,y)直线,注意这里是多条不是一条,因为x可以变化。然后再减去有交点的(x,y)直线和无交点的直线的数量。