首页 > 其他分享 >P5911 [POI2004]PRZ——状压dp

P5911 [POI2004]PRZ——状压dp

时间:2022-08-27 17:48:05浏览次数:124  
标签:le int POI2004 sum 状压 P5911 allt dp

一样,从\(n\le 16\)启发用状压dp

思路

本质上与UVA11825 Hackers' Crackdown异曲同工,不过可以通过预处理处理出一组人的集合
时间复杂度最坏为\(O(2^{2n})\),当任何一个集合中体重之和都\(\le W\),但实际运行起来很快

代码

#include <bits/stdc++.h>

using namespace std;
const int N=17,INF=0x3f3f3f3f;

int W,n,bound;
int t[N],w[N];

int S[1<<N],T[1<<N],cnt;
int f[1<<N];

void init() {
	bound=(1<<n)-1;
	for(int i=1;i<=bound;i++) {
		int sum=0,allt=0;
		for(int j=0;j<n;j++)
			if(i>>j&1) {
		  		sum+=w[j];
				allt=max(allt,t[j]);
			}
		if(sum<=W) {
		  	S[++cnt]=i;
			T[cnt]=allt;
		}
	}
}

int main() {
	scanf("%d%d",&W,&n);
	for(int i=0;i<n;i++)
	  scanf("%d%d",&t[i],&w[i]);
	init();	//预处理
	memset(f,0x3f,sizeof(f));
	f[0]=0;
	for(int i=0;i<=bound;i++) {
		if(f[i]==INF) continue;
		for(int j=1;j<=cnt;j++) {
			int k=S[j];
			if((i&k)!=0) continue;	//无交集
			f[i|k]=min(f[i|k],f[i]+T[j]);	//状态转移
		}
	}
	printf("%d",f[bound]);
	return 0;
}

标签:le,int,POI2004,sum,状压,P5911,allt,dp
From: https://www.cnblogs.com/wyc06/p/16631003.html

相关文章

  • P2622 关灯问题II——状压dp
    本题是一道十分好的状压dp练手题基本思路初看这道题时其实并没有什么思路,在看到\(n\le10\)时才想到使用状压dp有时候搜索时间复杂度很高,也没有方法优化到多项式复杂度,......
  • 状压DP-1755. 最接近目标值的子序列和
    问题描述给你一个整数数组nums和一个目标值goal。你需要从nums中选出一个子序列,使子序列元素总和最接近goal。也就是说,如果子序列元素和为sum,你需要最小化绝......
  • 状压DP-1815. 得到新鲜甜甜圈的最多组数
    问题描述有一个甜甜圈商店,每批次都烤 batchSize 个甜甜圈。这个店铺有个规则,就是在烤一批新的甜甜圈时,之前所有 甜甜圈都必须已经全部销售完毕。给你一个整数batchSi......
  • 状压dp
    朴素状压对于数据范围小的题一定要对状压绝对敏感这里的范围小不一定是\(n\)的范围小,而是任何有关信息小于\(20\)时要引起注意P3052[USACO12MAR]CowsinaSkyscr......