百度之星作为座位调整java_百度之星2006年初赛 座位调整

做法就是KM算法

我的建图过程如下:

把食品供应点拆开,不要让他成为一个点,如果一个食品供应点能够供应2个人,那就把它拆开成两个点,由于食品供应点的所有人数之和是等于员工数的,所以刚好构成一个两边点数一样的一个二分图,然后从员工到供应点连边的边权就是喜好度,然后再用KM算法进行最大带权匹配就好了,最后建的图是一个M*M的矩阵,由于M小于300,所以KM算法能够过。

也见到过别人用DP过掉的,不过没有想通。。DP一直很弱。。

话说我已经退役了,这个博客很少用了。。

#include

#include

#include

#define inf 99999999

#define maxn 305

using namespace std;

int n,m;

int a[maxn];

int map[maxn][maxn];

int temp[maxn][maxn];

int link[maxn];

int lx[maxn],ly[maxn];

bool x[maxn],y[maxn];

bool dfs(int u)

{

int i;

x[u]=true;

for(i=1;i<=n;i++)

{

if(lx[u]+ly[i]==map[u][i]&&!y[i])

{

y[i]=true;

if(link[i]==-1||dfs(link[i]))

{

link[i]=u;

return true;

}

}

}

return false;

}

int main()

{

int i,j,k,num;

while(scanf("%d%d",&m,&n)!=EOF)

{

for(i=1;i<=m;i++)

scanf("%d",&a[i]);

for(i=1;i<=n;i++)

for(j=1;j<=m;j++)

scanf("%d",&temp[i][j]);

for(i=1;i<=n;i++)

{

num=0;

for(j=1;j<=m;j++)

{

for(k=1;k<=a[j];k++)

{

num++;

map[i][num]=temp[i][j];

}

}

}

memset(x,0,sizeof(x));

memset(y,0,sizeof(y));

memset(link,-1,sizeof(link));

memset(ly,0,sizeof(ly));

for(i=0;i

lx[i]=inf;

for(k=1;k<=n;k++)

{

while(1)

{

memset(x,0,sizeof(x));

memset(y,0,sizeof(y));

if(dfs(k))

break;

int d=inf;

for(i=1;i<=n;i++)

if(x[i])

for(j=1;j<=n;j++)

if(!y[j]&&lx[i]+ly[j]-map[i][j]

d=lx[i]+ly[j]-map[i][j];

for(i=1;i<=n;i++)

if(x[i])

lx[i]=lx[i]-d;

for(i=1;i<=n;i++)

if(y[i])

ly[i]=ly[i]+d;

}

}

int ans1=0,ans2=0;

for(i=1;i<=n;i++)

ans1=ans1+map[link[i]][i];

printf("%d\n",ans1);

}

return 0;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值