1157. 【GDOI2004】可怜的绵羊 (Standard IO)
1157. 【GDOI2004】可怜的绵羊 (Standard IO)
由于这道题的数据特别小(n<=100),所以我们可以考虑较为暴力的做法。
首先扩倍,由于是按逆时针顺序给出各个树桩所在的坐标,所以。。。是为了后面的方便。。无所谓了。
我们先预处理t[i][j][k]表示以i,j,k为顶点的三角形是否存在即(三角形里不存在毒药),若存在t[i][j][k]=面积,若不存在为0;
我们先考虑如何求t;我们首先可以对于任何一个三角形可以把其分为以下两种
分别记录一下三条线的y=kx+b;然后暴力扫一遍m,然后分类讨论(以第二高的点划分然后,分上下讨论)看一下三角形里有没有毒,若有return0;else return S=sqrt(q(q-a)(q-b)(q-c)); 。。。。。你们有更好的方法就。。。别打击我。
这里理论来说应该是O(n^4)的,可能数据水了,或跑不满剪了许多。
然后设f[i][j]表示i必选以j为结尾i--->j中可划分的最大值(从i开始逆时针到j),我们枚举i,然后逆时针枚举j,每次从i<k<j,中选出k来转移,转移显然;分f[i][j]=max{f[i][j],f[i][k]+t[i][k][j]}不过这里要特判一下,毒药恰好在两个三角形边界上的情况。例如:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
struct nup{int x,y;}a[301],b[101];
int i,j,n,m,bz[201];
double t[202][202][202],ans,ans1,ans2,k,l,r,z,f[211][211];
void in(double &k,double &z,int a,int b,int a1,int b1)
{
if(b==b1){k=0,z=b;return;}
a-=a1;b-=b1;k=a*1.0/b;z=a1-k*b1;
}
int abss(int x){return(x>0?x:-x);}
double pd(int x,int y,int x1,int y1,int x2,int y2)
{
if(y<y1){swap(x,x1);swap(y,y1);}if(y<y2){swap(x,x2);swap(y,y2);}
if(x1>x2){swap(x1,x2);swap(y1,y2);}
double l,k,r,l1,k1,r1,l2,k2,r2,z,z1,z2;//l=kr+z;
in(k,z,y,x,y1,x1); in(k1,z1,y,x,y2,x2); in(k2,z2,y1,x1,y2,x2);
if(y1>y2)
{
for(int i=1;i<=m;i++)
{
if(b[i].y<=y&&b[i].y>=y1)
{
double xx=(b[i].y-z)*1.0/k;double xx1=(b[i].y-z1)*1.0/k1;
if(x==x1) xx=x1;if(x==x2)xx1=x;if(xx>xx1) swap(xx,xx1);
if(b[i].x>=xx&&b[i].x<=xx1) return 0;
}
else
if(b[i].y<=y1&&b[i].y>=y2)
{
double xx=(b[i].y-z2)*1.0/k2;double xx1=(b[i].y-z1)*1.0/k1;
if(x1==x2) xx=x1;if(x2==x) xx1=x;if(xx>xx1) swap(xx,xx1);
if(b[i].x>=xx&&b[i].x<=xx1) return 0;
}
}
}
else
{
for(int i=1;i<=m;i++)
{
if(b[i].y<=y&&b[i].y>=y2)
{
double xx=(b[i].y-z)*1.0/k;double xx1=(b[i].y-z1)*1.0/k1;
if(x==x1) xx=x;if(x2==x) xx1=x;if(xx>xx1) swap(xx,xx1);
if(b[i].x>=xx&&b[i].x<=xx1) return 0;
}
else
if(b[i].y<=y2&&b[i].y>=y1)
{
double xx=(b[i].y-z2)*1.0/k2;double xx1=(b[i].y-z)*1.0/k;
if(x==x1) xx=x;if(x2==x1) xx1=x1;if(xx>xx1) swap(xx,xx1);
if(b[i].x>=xx&&b[i].x<=xx1) return 0;
}
}
}
double s,s2,s1;
s=sqrt(abss(x-x1)*abss(x-x1)+abss(y-y1)*abss(y-y1));
s1=sqrt(abss(x-x2)*abss(x-x2)+abss(y-y2)*abss(y-y2));
s2=sqrt(abss(x2-x1)*abss(x2-x1)+abss(y2-y1)*abss(y2-y1));
double p=(s+s1+s2)*1.0/2;
double res=sqrt(p*(p-s)*(p-s1)*(p-s2));
return res;
}
double max1(double x,double y){return(x>y?x:y);}
int main()
{
//freopen("a.in","r",stdin);
scanf("%d",&n);
for(i=1;i<=n;i++)scanf("%d%d",&a[i].x,&a[i].y),a[i].x+=10000,a[i].y+=10000,a[n+i].x=a[i].x,a[n+i].y=a[i].y;
scanf("%d",&m);
for(i=1;i<=m;i++)scanf("%d%d",&b[i].x,&b[i].y),b[i].x+=10000,b[i].y+=10000;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
if(i!=j) for(int kk=1;kk<=n;kk++)
if(kk!=i&&kk!=j)
{
t[i][j][kk]=pd(a[i].x,a[i].y,a[j].x,a[j].y,a[kk].x,a[kk].y);
t[i+n][j][kk]=t[i][j+n][kk]=t[i][j][kk+n]=t[i+n][j+n][kk]=t[i+n][j][kk+n]=t[i][j+n][kk+n]=t[i+n][j+n][kk+n]=t[i][j][kk];
}
for(i=1;i<=n;i++)
{
for(j=i+1;j<i+n;j++)
{
for(int kk=i+1;kk<j;kk++)
{
if(t[i][kk][j]!=0)f[i][j]=max1(f[i][j],f[i][kk]+t[i][kk][j]);
}
ans2=max1(ans2,f[i][j]);
}
}
if(ans2!=0)printf("%.2lf",ans2);else printf("die");
}
这是AC的
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
struct nup{int x,y;}a[301],b[101];
int i,j,n,m,bz[201];
double t[202][202][202],ans,ans1,ans2,k,l,r,z,f[211][211];
void in(double &k,double &z,int a,int b,int a1,int b1)
{
if(b==b1){k=0,z=b;return;}
a-=a1;b-=b1;k=a*1.0/b;z=a1-k*b1;
}
int abss(int x){return(x>0?x:-x);}
double pd(int x,int y,int x1,int y1,int x2,int y2)
{
if(y<y1){swap(x,x1);swap(y,y1);}if(y<y2){swap(x,x2);swap(y,y2);}
if(x1>x2){swap(x1,x2);swap(y1,y2);}
double l,k,r,l1,k1,r1,l2,k2,r2,z,z1,z2;//l=kr+z;
in(k,z,y,x,y1,x1); in(k1,z1,y,x,y2,x2); in(k2,z2,y1,x1,y2,x2);
if(y1>y2)
{
for(int i=1;i<=m;i++)
{
if(b[i].y<=y&&b[i].y>=y1)
{
double xx=(b[i].y-z)*1.0/k;double xx1=(b[i].y-z1)*1.0/k1;
if(x==x1) xx=x1;if(x==x2)xx1=x;if(xx>xx1) swap(xx,xx1);
if(b[i].x>xx&&b[i].x<xx1) return 0;
}
else
if(b[i].y<=y1&&b[i].y>=y2)
{
double xx=(b[i].y-z2)*1.0/k2;double xx1=(b[i].y-z1)*1.0/k1;
if(x1==x2) xx=x1;if(x2==x) xx1=x;if(xx>xx1) swap(xx,xx1);
if(b[i].x>xx&&b[i].x<xx1) return 0;
}
}
}
else
{
for(int i=1;i<=m;i++)
{
if(b[i].y<=y&&b[i].y>=y2)
{
double xx=(b[i].y-z)*1.0/k;double xx1=(b[i].y-z1)*1.0/k1;
if(x==x1) xx=x;if(x2==x) xx1=x;if(xx>xx1) swap(xx,xx1);
if(b[i].x>xx&&b[i].x<xx1) return 0;
}
else
if(b[i].y<=y2&&b[i].y>=y1)
{
double xx=(b[i].y-z2)*1.0/k2;double xx1=(b[i].y-z)*1.0/k;
if(x==x1) xx=x;if(x2==x1) xx1=x1;if(xx>xx1) swap(xx,xx1);
if(b[i].x>xx&&b[i].x<xx1) return 0;
}
}
}
double s,s2,s1;
s=sqrt(abss(x-x1)*abss(x-x1)+abss(y-y1)*abss(y-y1));
s1=sqrt(abss(x-x2)*abss(x-x2)+abss(y-y2)*abss(y-y2));
s2=sqrt(abss(x2-x1)*abss(x2-x1)+abss(y2-y1)*abss(y2-y1));
double p=(s+s1+s2)*1.0/2;
double res=sqrt(p*(p-s)*(p-s1)*(p-s2));
return res;
}
double max1(double x,double y){return(x>y?x:y);}
int ppd(int x,int y,int x1,int y1)
{
for(int i=1;i<=m;i++){if(min(x,x1)<b[i].x&&b[i].x<max(x,x1)&&b[i].y<max(y,y1)&&min(y,y1)<b[i].y) return 0;}
return 1;
}
int main()
{
//freopen("a.in","r",stdin);
scanf("%d",&n);
for(i=1;i<=n;i++)scanf("%d%d",&a[i].x,&a[i].y),a[i].x+=10000,a[i].y+=10000,a[n+i].x=a[i].x,a[n+i].y=a[i].y;
scanf("%d",&m);
for(i=1;i<=m;i++)scanf("%d%d",&b[i].x,&b[i].y),b[i].x+=10000,b[i].y+=10000;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
if(i!=j) for(int kk=1;kk<=n;kk++)
if(kk!=i&&kk!=j)
{
t[i][j][kk]=pd(a[i].x,a[i].y,a[j].x,a[j].y,a[kk].x,a[kk].y);
t[i+n][j][kk]=t[i][j+n][kk]=t[i][j][kk+n]=t[i+n][j+n][kk]=t[i+n][j][kk+n]=t[i][j+n][kk+n]=t[i+n][j+n][kk+n]=t[i][j][kk];
}
for(i=1;i<=n;i++)
{
for(j=i+1;j<i+n;j++)
{
for(int kk=i+1;kk<j;kk++)
{
if(t[i][kk][j]!=0&&ppd(a[i].x,a[i].y,a[kk].x,a[kk].y)==1)
{
if(f[i][kk]+t[i][kk][j]>f[i][j])f[i][j]=f[i][kk]+t[i][kk][j];
}
}
ans2=max1(ans2,f[i][j]);
}
}
if(ans2!=0)printf("%.2lf",ans2);else printf("die");
}
这是加判断WA的

浙公网安备 33010602011771号