共鸣(resonance)

共鸣(resonance)

题目描述

 

GHQ通过在24区引起基因组共鸣,从而引发了第二次失落的圣诞。

24区的地图可以视为一个二维平面。GHQ在24区布置了m架发射塔,而葬仪社也建立了n个据点。要阻止共鸣,需要顺次连接一些据点,连接的两个据点之间会形成屏障。所有屏障应构成一个多边形,称之为干扰场。干扰场的面积越大,起到的干扰效果就越强。

但是并非所有的连接方式都是有效的。其一,任意两块屏障不能在据点之外的位置相交;其二,干扰场中的任意一个位置都应该可以直接看到构成干扰场的所有据点。所谓直接看到是指视线不会穿过任意一块屏障。

更重要的一点是,干扰场内不能存在有GHQ布置的发射塔,而且屏障也不能穿过发射塔。如果这个条件不满足,干扰场根本无法发挥作用。

葬仪社需要设计一个构成干扰场的方案,使得干扰场的面积最大。请你协助他们。

 

输入

 

 

输入文件的第一行包含两个整数n和m,分别代表葬仪社的据点个数,以及GHQ设立的发射塔架数。

接下来n行,每行包含一个坐标,表示葬仪社的一个据点的位置。

接下来m行,每行包含一个坐标,表示GHQ布置的一架发射塔的位置。

坐标的每一维皆为绝对值不超过1000的整数。输入的任意两个坐标不相同。

 

输出

 

 

第一行输出一个非负实数,表示干扰场的最大面积。保留两位小数。

接下来的一行输出一个非负整数t,代表构成干扰场的据点数。

接下来的一行,按照顺时针或者逆时针顺序输出构成干扰场的t个顶点。

如果有多种构成面积最大的干扰场的方案,输出任意一个即可。

特别地,如果不存在拥有正面积的干扰场,则构成干扰场的据点数视为0。即,第二行输出0,第三行输出一个空行。

 

样例输入

【样例输入1】
3 1
0 0
3 0
0 4
1 1
【样例输入2】
4 1
0 0
3 0
3 3
0 3
1 0

样例输出

【样例输出1】
0.00
0
【样例输出2】
4.50
3
4 2 3

提示

 

 

【样例1解释】

唯一的正面积干扰场是由据点1、2、3构成的,但是发射塔1在这个干扰场内部,所以不存在合法的正面积干扰场。

注意第三行的空行。

【样例2解释】

如下图所示:

 

图中的点A、B、C、D对应据点1到4,点E对应发射塔1。有色部分为构成的干扰场。另外一组可行的解为据点1、3、4构成的干扰场。可以证明不存在面积更大的干扰场,或者其他面积相同的干扰场。

 

【评分方法】

此题有部分分。如果不存在输出文件,或者输出不符合规范,得0分。

如果面积正确,构造的方案是一个多边形但是不合法或者不正确,得3分。

如果面积正确,而且构造的方案正确,得5分。

【数据规模和约定】

所有测试点的数据规模如下:

测试点编号

n

m

1

n<=10

m<=10

2

3

4

5

n<=100

m=0

6

7

8

9

n<=50

m<=50

10

11

12

13

14

15

N<=100

m<=100

16

17

18

19

20

 

solution

暴力

先枚举起点S,然后另f[i][j]表示我当前走到i,上一步是j的最大面积

f[k][i]=f[i][j]+size(k,i,S)

然后把上下合并起来

#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#define maxn 102
#define eps 1e-4
#define inf 1e9
using namespace std;
int n,m,fr[maxn][maxn],gr[maxn][maxn],ansp[maxn],ansq[maxn],cntp,cntq;
bool flag[maxn][maxn][maxn];
struct po{
    double x,y;int id;
}jd[maxn],fst[maxn];
double f[maxn][maxn],g[maxn][maxn],si[maxn][maxn][maxn];
bool cmp(po a,po b){
    if(a.x==b.x)return a.y<b.y;
    return a.x<b.x;
}
po xl(po a,po b){
    po t;t.x=b.x-a.x;t.y=b.y-a.y;
    return t;
}
double cj(po a,po b){
    return a.x*b.y-a.y*b.x;
}
bool pd(po a,po b ,po c){
    po x=xl(a,b),y=xl(b,c),z=xl(c,a);
    for(int i=1;i<=m;i++){
        po t1=xl(a,fst[i]),t2=xl(b,fst[i]),t3=xl(c,fst[i]);
        if(cj(t1,x)>=0&&cj(t2,y)>=0&&cj(t3,z)>=0)return 0;
        if(cj(t1,x)<=0&&cj(t2,y)<=0&&cj(t3,z)<=0)return 0;
    }
    return 1;
}
double size(po a,po b,po c){
    po x=xl(a,b),y=xl(b,c);
    double sum=abs(cj(x,y));
    return sum/2;
}
int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++){scanf("%lf%lf",&jd[i].x,&jd[i].y);jd[i].id=i;}
    for(int i=1;i<=m;i++)scanf("%lf%lf",&fst[i].x,&fst[i].y);
    sort(jd+1,jd+n+1,cmp);
    for(int i=1;i<=n;i++)
    for(int j=1;j<=n;j++)
    for(int k=1;k<=n;k++){
        if(pd(jd[i],jd[j],jd[k]))flag[i][j][k]=1;
        si[i][j][k]=size(jd[i],jd[j],jd[k]);
    }
    double ans=0;
    for(int S=1;S<=n;S++){
        for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)f[i][j]=g[i][j]=-inf;
        for(int i=S+1;i<=n;i++)f[S][i]=g[S][i]=0;
        for(int i=S;i<=n;i++)
        for(int j=i+1;j<=n;j++)
        for(int k=j+1;k<=n;k++){
            po k1=xl(jd[i],jd[j]),k2=xl(jd[i],jd[k]);
            if(cj(k1,k2)>=0&&flag[S][j][k]){
            	if(f[i][j]+si[S][j][k]>f[j][k]){
                	f[j][k]=f[i][j]+si[S][j][k];
            		fr[j][k]=i;
                }
            }
        }
        for(int i=S;i<=n;i++)
        for(int j=i+1;j<=n;j++)
        for(int k=j+1;k<=n;k++){
            po k1=xl(jd[i],jd[j]),k2=xl(jd[i],jd[k]);
            if(cj(k1,k2)<=0&&flag[S][j][k]){
                if(g[i][j]+si[S][j][k]>g[j][k]){
                	g[j][k]=g[i][j]+si[S][j][k];
                	gr[j][k]=i;
                }
            }
        }
        for(int T=S+1;T<=n;T++){
            for(int i=S;i<=T;i++){
                for(int j=S;j<=T;j++){
                	if(f[i][T]+g[j][T]>ans){
                    	ans=f[i][T]+g[j][T];
                    	int ii=i,tt=T;cntp=2;
                    	ansp[1]=T,ansp[2]=i;
                        while(ii!=S){
                            int tmp=ii;ii=fr[ii][tt];tt=tmp;
                            ansp[++cntp]=ii;
                        }
                        ii=j,tt=T,cntq=1;
                        ansq[1]=j;
                        while(ii!=S){
                            int tmp=ii;ii=gr[ii][tt];tt=tmp;
                            ansq[++cntq]=ii;
                        }
                	}
                }
            }
        }
    }
    printf("%.2lf\n",ans);
    if(!(cntp+cntq)){puts("0");return 0;}
    cout<<cntp+cntq-1<<endl;
    for(int i=1;i<=cntp;i++)cout<<jd[ansp[i]].id<<' ';
    for(int j=cntq-1;j>=1;j--)cout<<jd[ansq[j]].id<<' ';
    cout<<endl;
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值