1、本题用回溯法,刚开始我被样例误导,数组开小了,WA了一次。
2、用位运算可以节省vis数组。。。不过影响不大。。。
/*
ID:mrxy564
PROG:holstein
LANG:C++
*/
#include<cstdio>
#include<cstring>
using namespace std;
const int maxnum=2147483647;
int a[30],sum[30];
int b[20][30];
int c[20];
int n,m,num,state,cnt;
bool is_bigger(int a[],int b[]){
for(int i=0;i<n;i++)
if(a[i]<b[i]) return false;
return true;
}
void dfs(int cur){
if(cur==m){
int bit=1,temp=0;
memset(sum,0,sizeof(sum));
for(int i=0;i<m;i++){
if(state&bit){
for(int j=0;j<n;j++)
sum[j]+=b[i][j];
temp++;
}
bit<<=1;
}
if(is_bigger(sum,a)&&temp<num){
bit=1;cnt=0;
for(int i=0;i<m;i++){
if(state&bit)
c[cnt++]=i+1;
bit<<=1;
}
num=temp;
}
return;
}
state|=(1<<cur);
dfs(cur+1);
state&=~(1<<cur);
dfs(cur+1);
return;
}
int main(){
freopen("holstein.in","r",stdin);
freopen("holstein.out","w",stdout);
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
scanf("%d",&m);
for(int i=0;i<m;i++)
for(int j=0;j<n;j++)
scanf("%d",&b[i][j]);
num=maxnum;
state=0;
dfs(0);
printf("%d",num);
for(int i=0;i<num;i++)
printf(" %d",c[i]);
printf("\n");
return 0;
}
官方题解:
Since there are only 15 feeds, and for each feed we can either give zero or one scopes of it, there are 215 possible `feed mixtures' the cows can be fed, which is only 32,768. Therefore, try all combinations and pick which of the legal combinations uses the least number of feeds.
#include <stdio.h> #include <assert.h> #define MAXV 25 #define MAXF 15 int req[MAXV]; /* the vitamin requirements */ int numv; /* number of vitamins */ int feeds[MAXF][MAXV]; /* the vitamin within each feed */ int numf; /* number of feeds */ int best; /* the minimum number of feeds to use found thus far */ int bestf[MAXF]; /* the set */ int curf[MAXF]; /* the current set of feeds being considered */ void find_feed(int fcnt, int fid) { /* fcnt is the number of feeds in the current mixture, fid is the identifier of the first feed to try adding (last feed + 1) */ int lv; /* check if the requirement has been met */ for (lv = 0; lv < numv; lv++) if (req[lv] > 0) break; if (lv >= numv) { /* all the requirements are met */ /* we know this is better, since we wouldn't have checked it otherwise (see below) */ best = fcnt; for (lv = 0; lv < best; lv++) bestf[lv] = curf[lv]; return; } while (fid < numf && fcnt+1 < best) { /* try adding each feed to the mixture */ /* the fcnt+1 < best ensures that we stop if there's no hope in finding a better solution than one found already */ /* add the vitamins from this feed */ for (lv = 0; lv < numv; lv++) req[lv] -= feeds[fid][lv]; curf[fcnt] = fid; /* put it in the list */ find_feed(fcnt+1, fid+1); /* undo adding the vitamins */ for (lv = 0; lv < numv; lv++) req[lv] += feeds[fid][lv]; /* next feed */ fid++; } } int main(void) { FILE *fin, *fout; int lv, lv2; fin = fopen("holstein.in", "r"); fout = fopen("holstein.out", "w"); assert(fin); assert(fout); fscanf (fin, "%d", &numv); for (lv = 0; lv < numv; lv++) fscanf (fin, "%d", &req[lv]); fscanf (fin, "%d", &numf); for (lv = 0; lv < numf; lv++) for (lv2 = 0; lv2 < numv; lv2++) fscanf (fin, "%d", &feeds[lv][lv2]); best = numf+1; find_feed(0, 0); fprintf (fout, "%i", best); for (lv = 0; lv < best; lv++) fprintf (fout, " %i", bestf[lv]+1); fprintf (fout, "\n"); return 0; }