zoukankan      html  css  js  c++  java
  • 【题解】[USACO12MAR]Cows in a Skyscraper G

    题目链接

    题目大意:给定一个集合(S),给一个限制条件(P),要求划分集合,使得每一个子集(Ain S),(A)满足限制条件(P),且划分总数最小。

    注意到数据范围(n<=18).

    第一感状压。

    搜索不想写,于是(dp).

    原本设计的状态是(f[i][j])表示当前状态为(i),枚举到第(j)件物品的最大容量,(g[i][j])表示状态为(i),枚举到(j)的最小划分数。然而太复杂了,没有必要,写崩了搞了(16pts).

    换一种思路。设计(f[i])表示状态为(i)的最大容量,(g[i])表示状态为(i)的最小划分。显然,以(f)为第一关键字转移,若可以装,则优先转移该状态。遵循贪心策略,当前背包只要可以装,那就装。

    注意的是,需要更新背包数量的时候,注意要回归到(w-a[j])

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    //设计g[i]表示状态为i的背包最大容量 
    //f[i]表示状态为i的最小划分数
    //
    int n,w,ans=500;
    int a[18]; 
    int f[1<<18],g[1<<18];
    int main(){
    	scanf("%d%d",&n,&w);
    	for(int i=0;i<n;++i)scanf("%d",&a[i]);
    	sort(a,a+n);
    	memset(f,0x3f,sizeof(f));
    	g[0]=w;f[0]=1;
    	for(int i=0;i<(1<<n);++i){
    		for(int j=0;j<n;++j){
    			if(i&(1<<j))continue;
    			if(g[i]>=a[j]){
    				if(f[i]<=f[i|(1<<j)]){
    					f[i|(1<<j)]=f[i];
    					g[i|(1<<j)]=max(g[i|(1<<j)],g[i]-a[j]);
    				}
    			}
    			else{
    				if(f[i]+1<=f[i|(1<<j)]){
    					f[i|(1<<j)]=f[i]+1;
    					g[i|(1<<j)]=max(g[i|(1<<j)],w-a[j]);
    				}
    			}
    		}
    	}	
    	int T=(1<<n)-1;
    	cout<<f[T]<<endl;
    	return 0;
    }
    

    实现上可能有些许差异。注意两个数组代表的意义。

  • 相关阅读:
    编程语言是一种宗教
    execel 的java库
    c3p0配置学校
    Linux 文件命令精通指南
    几个WEB中常用的js方法
    不可多得的Javascript(AJAX)开发工具 - Aptana
    JDBC连不上Oracle数据库的解决方法
    利用PROFILE管理口令和资源
    ORACLE 数据库名、实例名、ORACLE_SID的区别
    用Java编写Oracle存储过程
  • 原文地址:https://www.cnblogs.com/h-lka/p/12422664.html
Copyright © 2011-2022 走看看