【Tai_mount】 算法学习 - 动态规划 -luoguP1049 [NOIP2001 普及组] 装箱问题

这道题其实非常非常简单,但是我中间好莫名其妙的搞了半天,晕。

最终是发现了两种写法:

求和

//https://www.luogu.com.cn/problem/P1049
#include<iostream>
#include<cstring>
using namespace std;
const int N=37,M=20007;
int vol,n,v[N],dp[M];

void input(){
	cin>>vol>>n;
	for(int i=1;i<=n;i++){
		cin>>v[i];
	}
}
void dpfun(){
	for(int i=1;i<=n;i++){
		for(int j=vol;j>0;j--){
			if(j<v[i]) continue;
			dp[j]=max(dp[j],dp[j-v[i]]+v[i]);
		} 
	}
}
void output(){
	cout<<vol-dp[vol];
}
int main(){
	input();
	dpfun();
	output();
	return 0;
}

这种方法就是,我们认为每个物品的价值就是它的体积。

就这么简单,是吧,我&@!%&#&¥!&%@&#*半天没想出来。

【Tai_mount菜死了】

算剩余

这方法是我一开始想的,但是万万妹想到啊,转移方程给写错了。

//https://www.luogu.com.cn/problem/P1049
#include<iostream>
#include<cstring>
using namespace std;
const int N=37,M=20007;
int vol,n,v[N],dp[M];

void input(){
	cin>>vol>>n;
	for(int i=1;i<=n;i++){
		cin>>v[i];
	}
}
void init(){
	for(int i=1;i<=vol;i++){
		dp[i]=i;
	}
}
void dpfun(){
	for(int i=1;i<=n;i++){
		for(int j=vol;j>0;j--){
			if(j<v[i]) continue;
			dp[j]=min(dp[j],dp[j-v[i]]);
		} 
	}
}
void output(){
	cout<<dp[vol];
}
int main(){
	input();
	init();
	dpfun();
	output();
	return 0;
}

要注意有初始化,就是dp[i]赋值i

这里的dp[j]算的事剩下的体积(也就是你要输出的那个东西)

转移方程:dp[j]=min(dp[j],dp[j-v[i]])

你可以利用dp[j]=j-sum[j]来推,这里的sum[j]就是第一种方法里的dp[j]

也可以直接算,不买就是dp[j],买就是dp[j-v[i]]+(j-(j-v[i]))-v[i],后面化简就只剩dp[i-v[i]]

@#¥()*了,我怎么推半天推错了

所以请一定动笔写

posted @ 2021-05-24 17:00  Tai_mount  阅读(191)  评论(0)    收藏  举报