战争

来源:互联网 发布:软件自动测试系统 编辑:程序博客网 时间:2024/06/09 19:21

战争

题目描述

X国和Y国是死对头,X国有N个炮台, Y国有M个基地和K个发电站,炮台、基地、发电站所在的位置的坐标都是整数。Y国的每个发电站能对距离其L以内(包括L)的基地供电。X国的每个炮台都可以发射无限次,每次发射可以击毁一个基地或者一个发电站,消耗的能量为两者距离的平方,这里的距离是欧几里德距离。X国决定要摧毁Y国的所有基地,我们说Y国的某个基地被摧毁的条件是:基地本身被直接摧毁或者对其供电的所有发电站被击。
X国摧毁Y国所有基地需要消耗的总能量最小是多少。
提示:点(X1,Y1)和点(X2,Y2)的欧几里德距离是:
dis = sqrt( (X2-X1)* (X2-X1) + (Y2-Y1)* (Y2-Y1)).

输入格式 1894.in

第一行:四个整数:NMKL1 <= NMK <= 50. 1<=L<=2000.
第二行:N个整数,第i个整数表示第i个炮台的横坐标。
第三行:N个整数,第i个整数表示第i个炮台的纵坐标。
第四行:M个整数,第i个整数表示第i个基地的横坐标。
第五行:M个整数,第i个整数表示第i个基地的纵坐标。
第六行:K个整数,第i个整数表示第i个发电站的横坐标。
第七行:K个整数,第i个整数表示第i个发电站的纵坐标。
所有的坐标的范围:[-500500]。所有的炮台、基地、发电站不会重复。
数据保证每个基地至少有一个发电站为其供电。

输出格式 1894.out

X国摧毁Y国所有基地需要消耗的总能量最小是多少。

输入样例 1894.in


题目大意:

    要用N个炮台把M个基地,或者可以给此基地供电的供电厂销毁。两个地方的距离为sqrt( (X2-X1)*(X2-X1) + (Y2-Y1)* (Y2-Y1)),需要的能量为:(X2-X1)* (X2-X1) +(Y2-Y1)* (Y2-Y1),也就是两个地方横纵坐标差的平方和。

    发电站供电的范围的距离在L以内。

    要得出把所有基地捣毁的最小能量。

70%的水分(112/161):

   虽然我觉得这种水分实在是太没道理,也可能是数据实在太弱,就是直接把摧毁所有基地需要的最小能量算出来(使用最近的炮台轰炸),再把摧毁所有发射站需要的最小能量算出来。

    我索性都没有判断哪些发射站可以给哪些基地供电,再把供不到电的基地格外再轰一次。不知道加多一些判断分数是否会更可观。

正解(161/161):

    很明显就是最小割的啦,每一个基地和发电站都是选择最近的炮台轰炸会最好,这样一来,N个炮台就没用了,只要事先预处理出每一个基地和每一个发电站是被多远的炮台所轰。

    构图:

    1、由源点s链接发电站,边权为最近炮台与发电站的距离。

    2、由汇点t链接基地,边权为最近炮台与基地的距离。

    3、发电站与可被发电的基地相连,边权为oo。

如图:

#include#include#include#includeusing namespace std;const int maxn=505,oo=100000000;int n,m,k,l;int px[maxn],py[maxn],jx[maxn],jy[maxn],fx[maxn],fy[maxn];//p炮台,j基地,f发射站 int cur=-1,head[maxn],s,t,v[2*maxn];long long ans;struct mi{int next,to,va;} edge[maxn*maxn]; void add(int from,int to,int va){cur++;edge[cur].to=to;edge[cur].va=va;edge[cur].next=head[from];head[from]=cur;}int Dis(int ax,int bx,int ay,int by)  {      ax-=bx;      ay-=by;      return ax*ax+ay*ay;  }  void init(){cin>>n>>m>>k>>l;for(int i=1;i<=n;i++) cin>>px[i];for(int j=1;j<=n;j++) cin>>py[j];for(int i=1;i<=m;i++) cin>>jx[i];for(int j=1;j<=m;j++) cin>>jy[j];for(int i=1;i<=k;i++) cin>>fx[i];for(int j=1;j<=k;j++) cin>>fy[j];memset(head,-1,sizeof(head));t=m+k+1;}void prepare(){ for (int i=1; i<=k; i++)      {          int d=oo;          for (int j=1; j<=n; j++) d=min(d, Dis(fx[i],px[j],fy[i],py[j]) );          add(0,i,d);          add(i,0,0);    }  //连发射站 for (int i=1; i<=m; i++)      {          int d=oo;          for (int j=1; j<=n; j++) d=min(d, Dis(jx[i],px[j],jy[i],py[j]) );          add(k+i,t,d);          add(t,k+i,0);    }  //连基地 for (int i=1; i<=k; i++)  {        for (int j=1; j<=m; j++){            if ( Dis(fx[i],jx[j],fy[i],jy[j])<=l* l){                  add(i,k+j,oo);                add(k+j,i,0);}}}//基地与发射站相连 } int dfs(int now,int mi){if(now==t) return mi;v[now]=1;int h=head[now];while(h!=-1){int to=edge[h].to,va=edge[h].va;if(v[to]==0&&va!=0){int kk;kk=dfs(to,min(va,mi));if(kk!=0){edge[h].va-=kk;edge[h^1].va+=kk;return kk;}}h=edge[h].next;}return 0;}/*int dfs(int cur,int mina){if(cur==t)return mina;v[cur]=1;int h=head[cur];while(h!=-1){int to=edge[h].to,va=edge[h].va;if(v[to]==0&&va!=0){int res=dfs(to,min(mina,va));if(res!=0){edge[h].va-=res;edge[h^1].va+=res;return res;}}h=edge[h].next;}return 0;}*/void start(){while(1){memset(v,0,sizeof(v));int res=0;res=dfs(0,oo);if(res==0) break;ans+=res;}}int main(){freopen("1894.in","r",stdin);freopen("1894.out","w",stdout);init();prepare();start();cout<


原创粉丝点击