Candy
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 164 Accepted Submission(s): 39
For each case starts with a line containing three integers N, M, K (1<=N<=13, 1<=M<=13, 2<=K<=10)
The next line contains M numbers which is B[i](0<=B[i]<=1000). Separated by a single space.
Then there are M*N like[i][j] , if the i-th kids like the j-th sugar like[i][j]=1 ,or like[i][j]=0.
2 3 2 2 2 2 0 0 0 0 0 1 3 2 2 2 2 0 0 0 0 0 0
Case #1: YES Case #2: NOHintGive the first and second candy to the first kid. Give the third candy to the second kid. This allocate make all kids happy.
题目:http://acm.hdu.edu.cn/showproblem.php?pid=4322
题意:有n块糖,m个小孩,每个小孩有喜欢的糖,把他喜欢的糖给他则他获得K的 高兴值,普通糖则获得1个高兴值,求能否使得所有小孩的高兴值都大于所给值
分析:这题比赛时一开始以为是DP,优化了n久还是TLE,后来想到了网络流,构建了一个类似题解的模型,可惜我还是嫩了点。。。模型是最大流,然后剩下的特殊处理,导致错误。。。。
正解就是最大费用流,首先给每个小孩限制糖果数,用的就是最大流,也就是我一开始想到的,其次在最大流的基础上加上费用,并把每个小孩的剩余值另立一条边,然后求最大费用最大流,在这里我想喷一下数据,居然少了一组,居然还有人过了。。。我悲剧的读入矩阵时,用单个变量就悲剧了,如果用数组的话,就会保留前一组数据,答案就对了。。。悲剧啊~~~
不过这题算个好题吧
代码:
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int oo=1e9;
const int mm=8888;
const int mn=44;
int node,src,dest,edge,need,sum;
int ver[mm],cost[mm],flow[mm],next[mm];
int head[mn],dis[mn],q[mn],p[mn],b[22],a[22][22];
bool vis[mn];
void prepare(int _node,int _src,int _dest)
{
node=_node,src=_src,dest=_dest;
for(int i=0;i<node;++i)head[i]=-1;
edge=0;
}
void addedge(int u,int v,int f,int c)
{
ver[edge]=v,flow[edge]=f,cost[edge]=c,next[edge]=head[u],head[u]=edge++;
ver[edge]=u,flow[edge]=0,cost[edge]=-c,next[edge]=head[v],head[v]=edge++;
}
bool spfa()
{
int i,u,v,l,r=0,tmp;
for(i=0;i<node;++i)dis[i]=oo;
dis[q[r++]=src]=0;
p[src]=p[dest]=-1;
for(l=0;l!=r;++l>=mn?l=0:l)
for(i=head[u=q[l]],vis[u]=0;i>=0;i=next[i])
if(flow[i]&&dis[v=ver[i]]>(tmp=dis[u]+cost[i]))
{
dis[v]=tmp;
p[v]=i^1;
if(vis[v])continue;
vis[q[r++]=v]=1;
if(r>=mn)r=0;
}
return p[dest]>-1;
}
int SpfaFlow()
{
int i,ret=0,delta;
while(spfa())
{
for(i=p[dest],delta=oo;i>=0;i=p[ver[i]])
if(flow[i^1]<delta)delta=flow[i^1];
for(i=p[dest];i>=0;i=p[ver[i]])
flow[i]+=delta,flow[i^1]-=delta;
ret-=delta*dis[dest];
sum+=delta;
}
return ret;
}
int main()
{
int i,j,n,m,k,t,cs=0;
scanf("%d",&t);
while(t--)
{
scanf("%d%d%d",&n,&m,&k);
prepare(n+m+2,0,n+m+1);
for(i=1;i<=n;++i)
addedge(src,i,1,0);
sum=need=0;
for(i=1;i<=m;++i)
{
scanf("%d",&b[i]);
if(b[i]>=k)addedge(n+i,dest,b[i]/k,-k);
if(b[i]%k>1)addedge(n+i,dest,1,-(b[i]%k));
need+=b[i];
}
for(i=1;i<=m;++i)
for(j=1;j<=n;++j)
{
scanf("%d",&a[i][j]);
if(a[i][j])addedge(j,n+i,1,0);
}
need-=SpfaFlow();
printf("Case #%d: ",++cs);
if(n-sum>=need)puts("YES");
else puts("NO");
}
return 0;
}