动态规划简单dp之判断一个数组中是否可以组成和为给定的数

#include
#include
using namespace std;

/**
 
判断一个正数 数组中的数是否可以组合起来 为一个给定的值 如果可以返回true   
*/


const int N=1010;

int a[N];

int dp[N][100];

//递归解法  从小标0开始到达i 判断是否可以有构成和为的s数 
bool fun(int i,int s){
	
	if(s==0) return true;
	
	else if(i==0)//到达第一个 
		return a[0]==s;//如果第0个刚好等于s 则返回true  不行则返回false
	else if(a[i]>s)//下标为i a[i]已经大于s 则不选
		return fun(i-1,s);
	else{
		
		//判断选与不选a[i] 
		bool t1=fun(i-1,s-a[i]);//这是选择了a[i]
		bool t2=fun(i-1,s);//不选
		return t1||t2; 
	}
	
}

//非递归解法 构建一个二维数组 dp[i][s] 表示从0到达i的时候 能否构建成和为s的真假值 

void fun2(int n,int s){
	
	
	for(int j=0;j<=s;j++)
	{
		dp[0][j]=0; 
	}
	//比如第0个的值为3  因为我们的dp[0][3] 表示从0到0是否可以组成3  所以dp[0][3] 直接为true 
	if(a[0]<=s)//当第0个已经比s要大 则显然无法来构建s 只能是小于s的时候
		dp[0][a[0]]=1; 
		 
	for(int i=0;i<n;i++)
		dp[i][0]=1;//当dp[i][j] 即要给定的值为0时 表示无需其他值来构建了 目前已完成则就是true了  
	
	//a[i][j]  表示从a[0] 到a[i] 是否可以组成j 的真假值
	//i从a[0]-a[n-1] j从0到给定值s	
	for(int i=1;i<n;i++){
		for(int j=1;j<=s;j++){
			if(a[i]>j)// a[i] 已经比j还要大了,很显然这个时候不选则a[i] 
				dp[i][j]=dp[i-1][s];
			else{
				int t3= dp[i-1][j-a[i]];//选择了a[i] 
				int t4=dp[i-1][j];//不选a[i] 
				dp[i][j]=(t3||t4);
			}
				
		}
	}
		
}

int main(void){
	
	int n,m;
	cin>>n>>m;
	for(int i=0;i<n;i++)
		cin>>a[i];
		 
	
//	if(fun(n-1,m)) 
//		cout<<"true"<
//	else
//		cout<<"false"<


	fun2(n,m);
	if(dp[n-1][m]) 
		cout<<"true"<<endl;
	else
		cout<<"false"<<endl;
} 

其中非递归的方式可以借助以下这张图来理解
动态规划简单dp之判断一个数组中是否可以组成和为给定的数_第1张图片

你可能感兴趣的:(算法)