计蒜客 蒜头君的积木

问题描述

蒜头君酷爱搭积木,他用积木搭了 n 辆重量为 wi的小车和一艘最大载重量为 W 的小船,他想用这艘小船将 n 辆小车运输过河。每次小船运载的小车重量不能超过 W。另外,小船在运载小车时,每辆小车会对小船有一个损坏值si,当多辆小车一起运载时,该趟运载对小船的损坏值为船上所有小车的最大损坏值。
现在蒜头君想知道,如何用小船运载 n 辆小车,可以使得对小船造成的总损坏值最小。


输入格式


第一行输入两个数 W 和 n(100≤w≤400,1≤n≤16),分别表示小船的最大载重量和小车总数。
接下来输入 n 行,每行输入两个整数si和 wi(1≤si ≤50,10≤wi≤100),分别表示每辆小车对小船的损坏值和每辆小车的重量。
输出格式 
输出一行,输出一个整数,表示用小船运载 nn 辆小车,最小的总损坏值。


样例输入


90 4
32 50
15 20
40 50
13 40


样例输出


72

#include<bits/stdc++.h>
using namespace std;
int W,N;
int minx=0x3f3f3f3f;
int s[20]={0},w[20]={0},dp[(1<<16)+10]={0};
int main(){
	scanf("%d%d",&W,&N);
	for(int i=1;i<=N;i++){
		scanf("%d%d",&s[i],&w[i]);
	}
	for(int i=0;i<(1<<N);i++){
		int ss=0,ww=0;//分别表示总的损坏值和总体积 
		for(int k=i,j=1;k;j++,k>>=1){
			if(k&1){
				ww+=w[j];
				ss=max(ss,s[j]);
			}	
		}
		if(ww<=W){
			dp[i]=ss;//小于最大载重量时损坏值的计算方法 
		}else{
			dp[i]=minx;
			for(int j=i;j;j=(j-1)&i){
				dp[i]=min(dp[i],dp[j]+dp[j^i]);
			}
		}
	}
	cout<<dp[(1<<N)-1]<<endl;//最后的结果输出所有的小车运载的值 
	return 0;
}

状压DP里的经典做法,枚举子集

for(int i=0;i<(1<<n);i++){

      for(int j=i;j;j=(j-1)&i){

           dp[i]=min(dp[i],dp[j]+dp[j^i]);
      }
}

猜你喜欢

转载自blog.csdn.net/amf12345/article/details/89001678