TYVJ 武器分配

来源:互联网 发布:电大简述时间管理矩阵 编辑:程序博客网 时间:2024/04/29 18:31

描述 Description

    后勤部队运来一批武器(机枪和盔甲)。你要把这些武器分配给手下的marine们(每人一部机枪,一套盔甲)。可是问题来了。。。
    这些武器的型号不相同(武器是由出价最低的承包商制造的),把一部m型的机枪和一套n型的盔甲分配给一个marine得到的不满意值为(m-n)^2(每个marine当然希望自己得到的武器是同一型号的)。
    你的任务就是把a部机枪和b套盔甲分配给手下n个marine。使他们的不满意值之和最小。

输入格式 InputFormat

第一行:3 个正整数 n , a , b (1<=n<=a,b<=80)
第二行:a 个数表示每部机枪的型号
第三行:b 个数表示每套盔甲的型号
0<=型号值<=10000

输出格式 OutputFormat

输出一个数:最小不满意值。

样例输入 SampleInput [复制数据]

Sample 1:2 3 39 10 200 10 11Sample 2:3 4 43 9 7 44 2 5 5

样例输出 SampleOutput [复制数据]

Sample 1:2Sample 2:5

题解

第一眼看有点像二分图匹配,但是有限定人数。所以用费用流。

直接在所有机枪和所有防弹衣之间连上有向边,边的费用为(a[i]-b[j])^2,容量为1。再加上超级源点0和第一汇点T1,费用为0,容量为1。

最后再加一个第二汇点T2,超级汇和第二汇点相连,费用为0,容量为n,用来进行人数限制。

最后来一次最小费用最大流就可以了。

#include<cstdio>#include<iostream>#include<cstdlib>#include<cstring>#include<cmath>#define inf 0x7fffffffusing namespace std;int n,a,b,x[82],y[82],T1,T2,zz=1,head[201];struct bian {int frm,to,v,nx,c;} e[50000];int from[201],dis[201],q[201],ans;bool pd[201];void insert(int u,int v,int w,int z){zz++; e[zz].frm=u; e[zz].to=v;e[zz].v=w; e[zz].c=z; e[zz].nx=head[u]; head[u]=zz;zz++; e[zz].frm=v; e[zz].to=u;e[zz].v=0; e[zz].c=-z; e[zz].nx=head[v]; head[v]=zz;}void build(){for(int i=1;i<=a;i++)for(int j=1;j<=b;j++)   insert(i,j+a,1,(x[i]-y[j])*(x[i]-y[j]));for(int i=1;i<=a;i++) insert(0,i,1,0);for(int i=1;i<=b;i++) insert(i+a,T1,1,0);insert(T1,T2,n,0);}void init(){scanf("%d%d%d",&n,&a,&b);for(int i=1;i<=a;i++) scanf("%d",&x[i]);for(int j=1;j<=b;j++) scanf("%d",&y[j]);T1=a+b+1; T2=T1+1;}bool spfa(){for(int i=0;i<=T2;i++) dis[i]=inf;int t=0,w=1,i;q[0]=dis[0]=0; pd[0]=1;while(t!=w)   {int p=q[t]; t=(t+1)%200;    i=head[p];    while(i)       {if(e[i].v&&dis[e[i].to]>dis[p]+e[i].c)       {from[e[i].to]=i;    dis[e[i].to]=dis[p]+e[i].c;    if(!pd[e[i].to])       {q[w]=e[i].to; pd[e[i].to]=1; w=(w+1)%200;}   }i=e[i].nx;   }pd[p]=0;   }if(dis[T2]==inf) return 0;return 1;}void getf(){int i,xx=inf;i=from[T2];while(i)   {xx=min(e[i].v,xx); i=from[e[i].frm];}i=from[T2];while(i)   {e[i].v-=xx; e[i^1].v+=xx;ans+=xx*e[i].c; i=from[e[i].frm];   }}void mcf(){while(spfa()) getf();}int main(){init(); build(); mcf();printf("%d",ans);return 0;}

0 0
原创粉丝点击