0
点赞
收藏
分享

微信扫一扫

砝码称重dp

和谐幸福的人生 2022-04-06 阅读 60
动态规划

砝码称重
好歹想到动态规划!!!
该有这样动态规划的思想,并不一定需要自己考虑周全,要让程序递推
前i个数是否能产生j这个数值

#include <iostream>
#include <algorithm>
#include <set>
using namespace std;
const int N=105;
int a[N];
int n;
int dp[N][100005];
//该有这样动态规划的思想,并不一定需要自己考虑周全,要让程序递推 
//前i个数是否能产生j这个数值 
signed main() {
	cin>>n;
	int sum=0;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		sum+=a[i];
	}
	//dp[1][a[1]]=1;
	//for(int i=1;i<=n;i++)dp[i][a[i]]=1;
	//其实提前多初始化一点绝对不是坏事,防止漏掉某条状态转移代码 
	for(int i=1;i<=n;i++){
		for(int j=1;j<=sum;j++){
			dp[i][j]|=dp[i-1][j]; 
			dp[i][a[i]]=1;//不要漏了这一条,除了前i-1个递推来的,
	//加上的第i个也可以搞出一个新状态 ,当然可以提前初始化这一点 
			dp[i][j+a[i]]|=dp[i-1][j];//累加总是可以的 
//在dp[i-1][j]的若干种情况下加入第i个砝码,能重新得到哪些
			if(a[i]>j)dp[i][a[i]-j]|=dp[i-1][j]; 
			if(a[i]<j)dp[i][j-a[i]]|=dp[i-1][j];
		}
	}
		/*
	dp[1][a[1]]=1;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=sum;j++){
			dp[i][j]=dp[i-1][j];//前i个发麻,j是否能从某些状态得到,非常明了 
//在dp[i-1][j]的若干种情况下加入第i个砝码,能重新得到哪些
			if(a[i]>j)dp[i][j]|=dp[i-1][a[i]-j]; 
			if(a[i]<j)dp[i][j]|=dp[i-1][j-a[i]];
			if(a[i]==j)dp[i][j]=1;
		}
	}
	
	统一一下形式,由于会递推到每一个i,j
	每次只考虑dp[i][j]由哪些状态转化而来就ok
	
	不要直接看由 dp[i-1][j]能得到哪些状态,
	虽然后者也可以,因为到i时,i-1的所有情况dp[i-1][j]
	一定已经提前算出来了(相当于上一行的所有值已经推出来了)
	1\注意状态只有0,1两种情况的,最好加上'|=',可以由众多状态推来
	但有些状态推不出,but在他之前有状态能推到,不能再被赋值为0了
	2\不管是考虑 未知状态可以由哪些状态推来 还是
	已知状态可以推出哪些状态,有点很重要,一定要考虑全面,不然很可能结果就为0 
	*/
	set<int> S;//其实大可不必,下面i就是不同的呀 
	S.clear(); 
	for(int i=1;i<=sum;i++) {
		if(dp[n][i])S.insert(i); 
	}
	cout<<S.size();
	return 0;
}
举报

相关推荐

B - 砝码称重

砝码称重 蓝桥杯

Java POJ 砝码称重

砝码称重C/C++

0 条评论