题目链接:http://acm.fafu.edu.cn/problem.php?id=1031
题目大意:小牛需要m种维生素,要从n种药品中选择最少的且字典序最小的组合并使得这些药品含有的卫生素均大于小牛需要的维生素量。
解题思路:模拟题,由于每种药品都只有选或者不选,我们可以用1至2^n内的每个数表示一个集合,这个数的j位为1说明这个集合含有第j个药品。然后更新答案,然后就没有然后了。
测试数据:
4
100 200 300 400
3
50 50 50 50
200 300 200 300
900 150 389 399
代码:
#include <stdio.h>
#include <string.h>
#define MIN 50
int need[MIN],arr[MIN][MIN],minn;
int n,m,ans[MIN],sum[MIN],have[MIN];
int Solve_1A() {
int i,j,k,tot;
minn = 16,ans[0] = 16; //最大
for (i = 1; i < (1<<n); ++i) {
tot = 0;
for (j = 0; j < n; ++j)
if (i >= (1<<j) && (i>>j) & 1)
have[tot++] = j;
if (tot > minn) continue;
memset(sum,0,sizeof(sum));
for (j = 0; j < tot; ++j)
for (k = 0; k < m; ++k)
sum[k] += arr[have[j]][k];
for (k = 0; k < m; ++k)
if (sum[k] < need[k]) break;
if (k == m && tot < minn) {
minn = tot;
for (j = 0; j < tot; ++j)
ans[j] = have[j];
for ( ; j < n; ++j) ans[j] = 16;
}
}
return minn;
}
int main()
{
int i,j,k;
while (scanf("%d",&m) != EOF) {
for (i = 0; i < m; ++i)
scanf("%d",&need[i]);
scanf("%d",&n);
for (i = 0; i < n; ++i)
for (j = 0; j < m; ++j)
scanf("%d",&arr[i][j]);
int cnt = Solve_1A();
printf("%d",cnt);
for (i = 0; i < cnt; ++i)
printf(" %d",ans[i]+1);
printf("\n");
}
}
本文ZeroClock原创,但可以转载,因为我们是兄弟。