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 0x3f3f3f3f

int ans[20],cnt;
int v[30],a[20][30],G;

int main()
{
    ofstream fout("holstein.out");
    ifstream fin("holstein.in");
    ///ifstream fin("lkl.txt");
    int n;
    while(fin>>n)
    {
        cnt=INF;
        for(int i=0;i<n;i++)
            fin>>v[i];
        fin>>G;
        for(int i=0;i<G;i++)
            for(int j=0;j<n;j++)
                fin>>a[i][j];
        int k=1<<G;
        for(int i=1;i<k;i++)
        {
             int test[30];
             int c=0,j=i;
             while(j)
             {
                 if(j&1)  c++;
                 j=j>>1;
             }
             if(c>cnt)
                continue;
             int tmp[30];
             memset(tmp,0,sizeof(tmp));
             j=i;
             int t=0;
             int m=0;
             while(j)
             {
                 if(j&1)
                 {
                     test[m++]=t;
                     for(int d1=0;d1<n;d1++)
                        tmp[d1]+=a[t][d1];
                 }
                 j=j>>1;
                 t++;
             }
             int i1=0;
             for(i1=0;i1<n;i1++)
                if(tmp[i1]<v[i1])
                   break;
             if(i1<n)
                continue;
             if(c==cnt)
             {
                 int d1,flag=0;
                 for(d1=0;d1<c;d1++)
                    if(ans[d1]>test[d1])
                    {
                         flag=1;
                          break;
                    }
                    else if(ans[d1]<test[d1])
                         break;
                 if(flag)
                 {
                     for(d1=0;d1<c;d1++)
                         ans[d1]=test[d1];
                 }
             }
             if(c<cnt)
             {
                 cnt=c;
                 for(int d1=0;d1<c;d1++)
                      ans[d1]=test[d1];
             }
        }
        fout<<cnt<<" ";
        for(int i=0;i<cnt-1;i++)
            fout<<ans[i]+1<<" ";
        fout<<ans[cnt-1]+1<<endl;
    }
  return 0;
}
时间: 2024-08-29 23:26:02

USACO--2.1Healthy Holsteins+状态压缩穷举的相关文章

C# FOR 语句——穷举

for循环.for 然后 tab键 自动生成下面的 for (int i = 0/*初始条件*/; i < length/*循环条件*/; i++/*状态改变*/) { } 穷举:把所有的可能性都列举出来 ①我有一元,两元,五元,有多少种可能,组合起来到20元. 公式:1*x+2*y+5*z=20 int a1 = 1, a2 = 2, a3 = 5, b = 20,c=0; for (int x = 1; x <=20; x++) //1元的可能性 { for (int y = 1; y &

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

描述 农民JOHN以拥有世界上最健康的奶牛为傲.他知道每种饲料中所包含的牛所需的最低的维他命量是多少.请你帮助农夫喂养他的牛,以保持它们的健康,使喂给牛的饲料的种数最少. 给出牛所需的最低的维他命量,输出喂给牛需要哪些种类的饲料,且所需的饲料剂量最少. 维他命量以整数表示,每种饲料最多只能对牛使用一次,数据保证存在解. 格式 PROGRAM NAME: holstein INPUT FORMAT: (file holstein.in) 第1行:一个整数V(1<=V<=25),表示需要的维他命的

zoj3777(状态压缩)

题目阐述: 给定n个座位,n个人,每个人可以做n个位置中的任意一个,P[i][j]代表第i个人做第j个位置获得的分数,求有多少种排列方式使得获得的分数大于等于M. 这道题跟数位dp的思想很像,都是穷举可能的方式,不过数位DP可以记忆化,这道题由于n较小,可以直接状态压缩. 定义状态d[i][s][t]代表已经放了i个座位,放的人数集合为s,获得分数为t的排列的数量. 然后每次暴力枚举每个位置可能会放的人 d[i][s | (1 << j)][t+ p[j][i]] +=d[i-1] [s] [

poj3254--Fields+状态压缩dp

第一道状态压缩dp :) 考虑每一行的情况,如果我们令0表示不可以放牧1表示放牧,那么这一行所有可行的情况都可以穷举出来并对应到一个十进制的数:这就是状态压缩.再由题目可以知道每一行的状态可不可以出现只和它前面的那一行有关,所以我们可以定义 dp[i][j]表示第i行处于第j种状态的时候有多少种放牧的方法: dp[i][j]=dp[i-1][j1]+dp[i-1][j2]+....+dp[i-1][jn],其中j要和jn能同时出现. 由这个方程我们就可以写程序了,我们可以选择用一个数组来表示状态

dp状态压缩

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

穷举迭代03/10

穷举迭代03/10 for循环拥有两类: 1.穷举: 把所有可能的情况都走一遍,使用if条件筛选出来满足条件的情况. for循环拥有两类: 2.穷举: 把所有可能的情况都走一遍,使用if条件筛选出来满足条件的情况. for循环  for(int i = 1; i<=5;i++) { 循环体: } while样式      int i= 1: while(表达式(i<=5)) { 循环体: 状态改变(i++): } do while 样式    do { 循环体: 状态改变(i++); }whi

for 穷举 迭代

for循环拥有两类:穷举:把所有可能的情况都走一遍,使用if条件筛选出来满足条件的情况. 迭代:从初始情况按照规律不断求解中间情况,最终推导出结果. 案例: //单位给发了一张150元购物卡, //拿着到超市买三类洗化用品. //洗发水15元,香皂2元,牙刷5元. //求刚好花完150元,有多少种买法, //每种买法都是各买几样? //设洗发水x 150/15==10 //牙刷y 150/5==30 //香皂z 150/2==75 int sum = 0; int biao = 0; for (

poj 3254 Corn Fields(状态压缩dp)

Description Farmer John has purchased a lush new rectangular pasture composed of M by N (1 ≤ M ≤ 12; 1 ≤ N ≤ 12) square parcels. He wants to grow some yummy corn for the cows on a number of squares. Regrettably, some of the squares are infertile and

for循环的应用:迭代法和穷举法

for()循环.四要素:初始条件,循环条件,状态改变,循环体.执行过程:初始条件--循环条件--循环体--状态改变--循环条件....注意:for的小括号里面分号隔开,for的小括号后不要加分号.for的嵌套.应用:迭代法,穷举法.一.迭代法:有一定规律. 每次循环都是从上次运算结果中获得数据,本次运算的结果都是要为下次运算做准备. 二.穷举法:用循环把各种可能的情况都给走一遍,然后用if条件把满足要求的结果给筛选出来.