题目:CSP模拟模拟考试——线性分类器
思路:题目要求将A,B两类带点完全分开,就要求在给定参数下带入A(B)类型的点求其值大于(或者小于)0的点数目,如果所有带入A类点的值大于0(或者小于0)的同时所有带入B类点的值都小于0(或者大于0),就是说明给定参数的这条直线完美分开了A,B两类点
代码:
#include<stdio.h>
#define N 1000
#define S 20
int main()
{
int i,j;
int x[N],y[N];//坐标
char type[N];//类型
int a[S],b[S],c[S];//直线的三个参数
int countA=0,countB=0,value=0;
int count_A_more=0,count_A_less=0,count_B_more=0,count_B_less=0;//more大于0,less小于0
int n,m;//点个数,查询个数
int flag=1;
while(1)
{
scanf("%d %d",&n,&m);
if(0<n&&n<=1000&&0<m&&m<=20)//子任务
{
break;
}
}
for(i=0;i<n;i++)
{
while(1)
{
scanf("%d %d %c",&x[i],&y[i],&type[i]);
if(type[i]=='A')
{
countA++;
}
if(type[i]=='B')
{
countB++;
}
if(type[i]=='A'||type[i]=='B')//类型只为A,B
{
break;
}
}
}
//printf("%d %d ",countA,countB);//验证类型A(B)的数目正确否
while(flag)//a+bx+cy=0(b,c不同时为0 )
{
for(i=0;i<m;i++)//输入m个查询
{
scanf("%d %d %d",&a[i],&b[i],&c[i]);
if((b[i]!=0||c[i]!=0)||(b[i]==0&&c[i]!=0)||(b[i]!=0&&c[i]==0))//a,b不同时为0
{
flag=0;
}
else
flag=1;
}
}
for(i=0;i<m;i++)
{
count_A_more=0,count_A_less=0,count_B_more=0,count_B_less=0;
for(j=0;j<n;j++)//外循环将参数定下来,然后,将点带入,判断值大于0还是小于0
{
value=a[i]+b[i]*x[j]+c[i]*y[j];//a+bx+cy>0||a+bx+cy<0
//printf("%d参数时value%d=%d\n",i,j,value);//验证值是否出错
if(type[j]=='A')
{
if(value>0)//count_A_more=0,count_A_less,count_B_more=0,count_B_less;//more大于0,less小于0
{
count_A_more++;
}
else
{
count_A_less++;
}
}
if(type[j]=='B')
{
if(value>0)
{
count_B_more++;
}
else
{
count_B_less++;
}
}
} //此循环结束可以得到带入点后4个count的值
//printf("count_A_more=%d\ncount_A_less=%d\ncount_B_more=%d\ncount_B_less=%d\n",count_A_more,count_A_less,count_B_more,count_B_less);
if((count_A_more==countA&&count_B_less==countB)||(count_A_less==countA&&count_B_more==countB)) //A,B两类已经分好
{
printf("Yes\n");
}
else
printf("No\n");
}
return 0;
}
运行结果截图: