USACO-Section 2.1 Healthy Holsteins (状态压缩DFS)

描述

农民JOHN以拥有世界上最健康的奶牛为傲。他知道每种饲料中所包含的牛所需的最低的维他命量是多少。请你帮助农夫喂养他的牛,以保持它们的健康,使喂给牛的饲料的种数最少。

给出牛所需的最低的维他命量,输出喂给牛需要哪些种类的饲料,且所需的饲料剂量最少。

维他命量以整数表示,每种饲料最多只能对牛使用一次,数据保证存在解。

格式

PROGRAM NAME: holstein

INPUT FORMAT:

(file holstein.in)

第1行:一个整数V(1<=V<=25),表示需要的维他命的种类数。

第2行:V个整数(1<=每个数<=1000),表示牛每天需要的每种维他命的最小量。

第3行:一个整数G(1<=G<=15),表示可用来喂牛的饲料的种数。

下面G行,第i行表示编号为i饲料包含的各种维他命的量的多少。

OUTPUT FORMAT:

(file holstein.out)

输出文件只有一行,包括

牛必需的最小的饲料种数P

后面有P个数,表示所选择的饲料编号(按从小到大排列)。

如果有多个解,输出饲料序号最小的(即字典序最小)。

SAMPLE INPUT

4
100 200 300 400
3
50 50 50 50
200 300 200 300
900 150 389 399

SAMPLE OUTPUT

2 1 3

第一反应又是贪心。。。但不知道第二步开始怎么贪,又看到最多有15种饲料,枚举不会超时,而且可以状态压缩。

ans从17位开始保存选取饲料的种数,前16位保存养料的取舍情况。

/*
ID: your_id_here
PROG: holstein
LANG: C++
*/
#include <cstdio>
#include <cstring>

using namespace std;

const int d=1<<16;
int v,cow[26],g,sco,num[17][26],ans,tmp,t,tot[26];

inline bool isLeagl() {
    for(int i=0;i<v;++i)
        if(tot[i]<cow[i])
            return false;
    return true;
}

void dfs(int n,int way) {//n表示已经选过了n种饲料,way从17位开始保存选的饲料数,前16位保存饲料的取舍情况
    if(n==g) {
        if((way>>16)<(ans>>16))
            if(isLeagl())
                ans=way;
        return ;
    }
    way+=d;//由于有多解时需要输出字典序最小的,所以先取当前饲料,则递归结束判断时就不用判断需要饲料种类相同的情况
    way|=1<<n;
    for(t=0;t<v;++t)
        tot[t]+=num[n][t];
    dfs(n+1,way);
    way-=d;
    way&=~(1<<n);
    for(t=0;t<v;++t)
        tot[t]-=num[n][t];
    dfs(n+1,way);
}

int main() {
    int i,j;
    freopen("holstein.in","r",stdin);
    freopen("holstein.out","w",stdout);
    while(1==scanf("%d",&v)) {
        for(i=0;i<v;++i)
            scanf("%d",cow+i);
        scanf("%d",&g);
        for(i=0;i<g;++i)
            for(j=0;j<v;++j)
                scanf("%d",&num[i][j]);
        memset(tot,0,sizeof(tot));
        tmp=0;
        ans=~(1<<31);//ans取最大值,主要是让记录使用饲料种类最大
        dfs(0,0);
        printf("%d",tmp=ans>>16);
        for(i=0;i<16;++i)
            if(ans&(1<<i))
                printf(" %d",i+1);
        printf("\n");
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-26 00:35:23

USACO-Section 2.1 Healthy Holsteins (状态压缩DFS)的相关文章

USACO Section 2.1 Healthy Holsteins

/* ID: lucien23 PROG: holstein LANG: C++ */ #include <iostream> #include <fstream> #include <vector> using namespace std; bool compFun(int x, int y) { int temp, i = 0; while (true) { temp = 1 << i; if (temp&x > temp&y) {

POJ2411——状态压缩+DFS——Mondriaan&#39;s Dream

Description Squares and rectangles fascinated the famous Dutch painter Piet Mondriaan. One night, after producing the drawings in his 'toilet series' (where he had to use his toilet paper to draw on, for all of his paper was filled with squares and r

USACO--2.1Healthy Holsteins+状态压缩穷举

最多有15种食物,然后对于每种食物有选或者不选两种情况,所以总的情况数只有2^15种,我们可以借助状态压缩,穷举出所有的状态,然后求出最好的情况. 代码如下: /* ID: 15674811 LANG: C++ TASK: holstein */ #include<iostream> #include<cstdio> #include<cstring> #include<fstream> using namespace std; #define INF 0x

SRM 628 DIV2 1000 CandleTimerEasy 状态压缩+DFS

题意:给你一个树型蜡烛,你可以从1个或多个叶子开始点蜡烛,问你能使蜡烛烧完以后能得到时间的个数. 解题思路:状态压缩枚举DFS, 解题代码: 1 // BEGIN CUT HERE 2 /* 3 4 */ 5 // END CUT HERE 6 #line 7 "CandleTimerEasy.cpp" 7 #include <cstdlib> 8 #include <cctype> 9 #include <cstring> 10 #include

ural 1500 Pass Licenses (状态压缩+dfs)

1500. Pass Licenses Time limit: 2.5 secondMemory limit: 64 MB A New Russian Kolyan believes that to spend his time in traffic jams is below his dignity. This is why he had put an emergency flashlight upon the roof of his Hummer and had no problems un

【USACO 2.1】Healthy Holsteins

/* TASK: holstein LANG: C++ URL: http://train.usaco.org/usacoprob2?a=SgkbOSkonr2&S=holstein SOLVE: con[i][j]为食物i含有维生素j的量,ned[i]为需要的维生素i的量 bfs,用二进制保存状态 */ #include<cstdio> #define N 30 int v,g,ned[N],con[N][N]; int now[N]; int l,r,q[40000]; bool

POJ-3279.Fliptile(二进制状态压缩 + dfs) 子集生成

昨天晚上12点刷到的这个题,一开始一位是BFS,但是一直没有思路.后来推了一下发现只需要依次枚举第一行的所有翻转状态然后再对每个情况的其它田地翻转进行暴力dfs就可以,但是由于二进制压缩学的不是很透,一直有小问题,下面我还会讲子集生成的相关方法,有兴趣的同学可以继续关注. 本题大意:一块地,有黑(1)白(0)之分,牛每次踩踏使得当前块以及四连块都变色,问当牛如何踩时使得地都变白并且求出最小踩踏次数和踩踏路径的最小字典序时的踩踏地图. 本题思路:由于同一块地被翻两次都会回到原来的状态,所以只需要对

[HDU]5094Maze(状态压缩BFS)

状态压缩的题,第一次WA了,怎么改都不对,交了十几遍,之后重新写了一个,1A了 #include<cstdio> #include<queue> #include<cstring> #include<algorithm> using namespace std; const int maxn = 51; const int dir[4][2] = {{0,1},{-1,0},{0,-1},{1,0}}; int n,m,t; int door[maxn][m

dp状态压缩

dp状态压缩 动态规划本来就很抽象,状态的设定和状态的转移都不好把握,而状态压缩的动态规划解决的就是那种状态很多,不容易用一般的方法表示的动态规划问题,这个就更加的难于把握了.难点在于以下几个方面:状态怎么压缩?压缩后怎么表示?怎么转移?是否具有最优子结构?是否满足后效性?涉及到一些位运算的操作,虽然比较抽象,但本质还是动态规划.找准动态规划几个方面的问题,深刻理解动态规划的原理,开动脑筋思考问题.这才是掌握动态规划的关键. 动态规划最关键的要处理的问题就是位运算的操作,容易出错,状态的设计也直