Fruit Ninja
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 841 Accepted Submission(s): 384
Problem Description
Fruit Ninja is a popular classic game. During the game, fruits will up to the air, and your aim is cut as more fruits as possible with a line
Even if the line touch a point of a fruit, the fruit also be cut.
Input
The first line is a number T(1<=T<=30), represents the number of case. The next T blocks follow each indicates a case.
The first line of each case contains one integer N (1<=N<=10)
Then N lines follow, each line contains a integer K(3<=K<=10), represent the number points of the fruit, then K*2 integers follow, each two integers represent one point of the fruit.(with anticlockwise order)
I promise all fruits are convex polygon, and any two fruit have no common point.
Output
For each case, output the number of case and the maximum fruits you could cut with a line.(as shown in the sample output)
Sample Input
2 3 3 0 0 1 0 1 1 3 1 2 2 1 2 2 3 3 1 3 0 4 0 3 4 0 0 1 0 1 1 0 1 4 2 0 3 0 3 1 2 1 4 0 99 1 99 1 100 0 100
Sample Output
Case 1: 3 Case 2: 2
Author
NotOnlySuccess
Source
2011 Alibaba Programming Contest
任意选取两个水果,并选出水果上两个端点组成一条直线去切割其他的水果,就是判断直线与线段是否相交(n^3*k^3)
注意:每个水果用一个凸多边形来表示。
这题是让你求一条线能够穿过最多的水果(碰到一个点也算)。
可以证明,枚举两个点组成的线是可行的。
因为假设有一条线穿过N个水果,那么把它平移一些使得还是穿过N个但是已经不能再平移了,这样的话,这条线肯定是在某个水果的某个端点上。
再以这个端点,旋转这条线,还是穿过N个,直到不能旋转为止(再旋转可能就不能穿过N个了),这样的话,肯定还是这条线碰到了另外一个端点。
所以只要枚举两个端点即可。
只有一个水果的话,特判下。
代码:
#include<stdio.h>
#define N 20
struct node
{
int x[N],y[N],sum;
}p[N];
int multi(int x1,int y1,int x2,int y2,int x0,int y0)
{
return ((x1-x0)*(y2-y0)-(x2-x0)*(y1-y0));
}
int main()
{
int t,cnt=1,max,i,j,k,q,l,r,ans,n,t1,t2;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%d",&p[i].sum);
for(j=0;j<p[i].sum;j++)
scanf("%d%d",&p[i].x[j],&p[i].y[j]);
}
if(n==1)//注意n=1的情况
{
printf("Case %d: %d\n",cnt++,1);
continue;
}
max=-1;
for(i=0;i<n;i++)
{
for(j=i+1;j<n;j++)
{
for(k=0;k<p[i].sum;k++)
{
for(l=0;l<p[j].sum;l++)
{
ans=2;
for(q=0;q<n;q++)
{
if(q==i||q==j)
continue;
for(r=0;r<p[q].sum-1;r++)
{//判断直线是否与线段相交
t1=multi(p[i].x[k],p[i].y[k],p[j].x[l],p[j].y[l],p[q].x[r],p[q].y[r]);
t2=multi(p[i].x[k],p[i].y[k],p[j].x[l],p[j].y[l],p[q].x[r+1],p[q].y[r+1]);
if(t1*t2<=0)
{
ans++;
break;
}
}
}
if(ans>max)
max=ans;
}
}
}
}
printf("Case %d: %d\n",cnt++,max);
}
return 0;
}
hdu 3952
最新推荐文章于 2017-09-04 16:18:45 发布