USACO Healthy Holsteins

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;
 }



 

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值