Candy
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 2333 Accepted Submission(s): 709
Problem Description
There are N candies and M kids, the teacher will give this N candies to the M kids. The i-th kids for the j-th candy has a preference for like[i][j], if he like the sugar, like[i][j] = 1, otherwise like[i][j] = 0. If the i-th kids get the candy which he like he will get K glad value. If he or she do not like it. He will get only one glad value. We know that the i-th kids will feel happy if he the sum of glad values is equal or greater than B[i]. Can you tell me whether reasonable allocate this N candies, make every kid feel happy.
Input
The Input consists of several cases .The first line contains a single integer t .the number of test cases.
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.
Output
If there have a reasonable allocate make every kid feel happy, output "YES", or "NO".
Sample Input
2 3 2 2 2 2 0 0 0 0 0 1 3 2 2 2 2 0 0 0 0 0 0
Sample Output
Case #1: YES Case #2: NO
Hint
Give the first and second candy to the first kid. Give the third candy to the second kid. This allocate make all kids happy.
一、原题地址
传送门
二、大致题意
现在有n颗糖需要分配给m个小朋友。每个小朋友对每颗糖有自己的喜好,用一个 01 矩阵来表示(1表示喜欢)。
如果一个小朋友被分到了一颗喜欢的糖,那么他会获得 K 点愉悦值,若分配到一颗不喜欢的糖则只得到一点愉悦值。
给出一组小朋友的开心值B[i],若某个小朋友的愉悦值达到了他对应的B[i],则他就会处于开心状态。
现在询问是否能使得所有的小朋友都处于开心状态。输出YES或者NO。
三、思路
对于分配的问题,想到的就是网络流。那么如何来建图呢。
首先建立一个超级源点,使它指向所有的糖,显然容量应为1。
再将所有的小朋友指向一个超级汇点,因为我们知道每个小盆友的开心值为Bi,并且也知道每一颗喜欢的糖可以为这个小朋友提供 K 点愉悦值,那么也就是说 Bi/K 就是这个小朋友应该被分配的喜欢的糖的个数(也就是这条边的容量)。但是Bi/K不一定是整数,那么此时我们就会陷入疑问,是再分一颗糖给他呢?还是把这颗糖分配给同样喜欢这颗糖的小朋友?所以我们意识到仅仅只利用最大流显然是不能解决这个问题的,此时只要再给每条边引入一个费用,那么我们就可以得到糖的分配优先级。
1、 对于Bi/K为整数的情况,我们肯定要优先这样分配,显然他的费用应该为最小,他的容量也就是Bi/K。
2、对于Bi/K不是整数的情况,若Bi%K的值越大,就越优先分糖,因为若不给这个小朋友分糖,那么他在之后拿取价值为1的糖时,将会占用更多的资源。
这样我们就建立了一个只分配喜欢的糖为依据的最小费用最大流。为什么只关于被喜欢的糖来建图呢,因为这样能保证这些糖的价值得到最好的使用,而那些不被喜欢的糖只能提供1的价值,我们是可以用作弥补分糖时部分小朋友留下的漏洞。
根据以上思路,我们可以用 rest 来记录跑完最小费用最大流之后还剩下的价值为1的糖的数量,然后我们从汇点遍历与他相邻的边,即与每个小朋友的流量,可以得到每个小朋友当前分得的喜欢的糖的个数记作use[i],那么他们当前的愉悦值就是use[i]*K。 之后就是检查一下剩下的糖数能否补全他们的愉悦值,然后输出判断就可以啦。
四、代码
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include