zoukankan      html  css  js  c++  java
  • P1460 健康的荷斯坦奶牛 Healthy Holsteins

    P1460 健康的荷斯坦奶牛 Healthy Holsteins


    题目描述

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

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

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

    输入输出格式

    输入格式:

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

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

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

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

    输出格式:

    输出文件只有一行,包括

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

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

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

    输入输出样例

    输入样例#1:
    4
    100 200 300 400
    3
    50  50  50  50
    200 300 200 300
    900 150 389 399
    输出样例#1:
    2 1 3
    

    说明

    USACO 2.1

    翻译来自NOCOW


    被卡了一个小时,第一次写剪纸的蒟蒻就是我。


    首先就是要枚举不重复的子集,根据测算,只需要枚举25 +24 +23  +...+1 = (25 + 1)*25/2个子集,所以时间复杂度是相当低的。
    但是如果枚举成25!的子集,一定会崩掉。


    我们为了避免枚举重复的子集,采取了这样的枚举自己方法(紫书里还有一种):

    枚举子集内元素个数1..n,并保证子集是单调递增的。这样就能够补充不漏的枚举子集。

    上代码。


    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    
    const int MAXN = 25 + 15;
    const int MAXM = 15 + 15;
    
    int n;
    int min[MAXN];
    int m;
    int value[MAXM][MAXN];
    
    int c[MAXN];
    
    int num[MAXN];
    bool b[MAXM];
    
    bool IsFull[MAXN];
    
    int ans;
    
    int cnt;
    bool ok;
    
    void dfs(int step,int pre)
    {
    	if(ok)return;
    	if(step > cnt + 1) return;
    	if(step == cnt + 1)
    	{
    		for(int i = 1;i <= n;i ++)
    		{
    			int sum = 0;
    			for(int j = 1;j <= cnt;j ++)
    			{
    				sum += value[num[j]][i];
    			}
    			if(sum < min[i])return;
    		}
    		ans = cnt;
    		ok  = true;
    		return;
    	}
    
    	for(int i = 1;i <= m;i ++)
    	{
    		if(ok)return;
    		if(i <= pre)continue; 
    		if(!b[i])
    		{
    			num[step] = i;
    			b[i] = true;
    			dfs(step + 1,i);
    			b[i] = false;
    		}
    	}
    }	
    
    int main()
    {
    	freopen("data.txt", "r", stdin);
    	ans = 99999999;
    	scanf("%d", &n);
    	for(int i = 1;i <= n;i ++)
    	{
    		scanf("%d", &min[i]);
    	}
    	scanf("%d", &m);
    	for(int i = 1;i <= m;i ++)
    	{
    		for(int j = 1;j <= n;j ++)
    		{
    			scanf("%d", &value[i][j]);
    		}
    	}
    	for(int i = 1;i <= m;i ++)
    	{
    		cnt ++;
    		dfs(1,0);
    		if(ok) break;
    	}	
    	printf("%d ", ans);
    	for(int i = 1;i <= ans;i ++)
    	{
    		printf("%d ", num[i]);
    	}
    	return 0;
    }



  • 相关阅读:
    (转载)C++ string中find() ,rfind() 等函数 用法总结及示例
    UVA 230 Borrowers (STL 行读入的处理 重载小于号)
    UVA 12100 打印队列(STL deque)
    uva 12096 The SetStack Computer(STL set的各种库函数 交集 并集 插入迭代器)
    uva 1592 Database (STL)
    HDU 1087 Super Jumping! Jumping! Jumping!
    hdu 1176 免费馅饼
    HDU 1003 Max Sum
    转战HDU
    hust 1227 Join Together
  • 原文地址:https://www.cnblogs.com/huibixiaoxing/p/6537732.html
Copyright © 2011-2022 走看看