连续邮资问题(DP)

连续邮资问题:
假设国家发行了n种不同面值的邮票,并且规定每张信封上最多只允许贴m张邮票。连续邮资问题要求对于给定的n和m的值,给出邮票面值的最佳设计,在一张信封上可以贴出从邮资1开始,增量为1的最大连续邮资区间。
 
举例分析:
当n=2,m=3时,如果面值分别为1和4,则可以获得的邮资范围为1~6 加上 8 , 9 , 12
因为8.9.12和1~6并不连续,使用最大能取到的是6

用动态规划的思想取b[i][v],表示至多 i 张邮票,邮资额为 v的逻辑值
b[i][v]能否取到取决于他的任一种前身能否取到,而它的前身就是b[i-1][v-xk],xk是任一小于v 的一张邮票票值

初始化:
b[0][v]=0, (v>0)
b[0][0]=1
#include <iostream>
#include<algorithm>
#include<vector> 
#include<fstream>
#include<iomanip>
#include<map>
#include<sstream>
#include<cmath> 
#include<stack>
using namespace std;
int dp[1000][1000]={-1};
bool b(int k,int v,int*a,int size){
	if(k<0||v<0||(k==0&&v>0))return false;
	if(v==0)return true;
	
	for(int i=0;i<size;i++){
		if(v>=a[i]){//因为是去并,因此只要里面有一个true,即可返回true 
			if(dp[k-1][v-a[i]]==-1){
				dp[k-1][v-a[i]] = b(k-1,v-a[i],a,size);
			}
			//printf("dp[%d][%d]=%d\n",k-1,v-a[i],dp[k-1][v-a[i]]);
			if(dp[k-1][v-a[i]]==1)return true;
			}
			else break;//本处假设邮票数组是递增的 
		}
	
	dp[k][v]=false;
	return dp[k][v];
} 
int getMax(int *a,int size,int k){
	for(int v=1;;v++){
		if(!b(k,v,a,size))return v-1;//返回首个false值的v值减一 
	}
}
int main(){
	int size;
	cin>>size;
	int *a = new int[size]();
	for(int i=0;i<size;i++){
		cin>>a[i]; 
	}
	dp[0][0] = 1;
	for(int i=0;i<1000;i++){
		for(int j=0;j<1000;j++)dp[i][j]=-1;
	}//初始化动态数组,取-1是为了标志此项未被赋过值,因此需要继续递归下去 
	
	//构建邮票票值数组 
	int k;//取的邮票张数 
	cin>>k;
	cout<<getMax(a,size,k);
    return 0;
}

方法二
                                                           动态方程                                                                    初始化           结果,n取的邮票数

#include <iostream>
#include<algorithm>
#include<vector> 
#include<fstream>
#include<iomanip>
#include<map>
#include<sstream>
#include<cmath> 
#include<stack>
# define inf 9999999
using namespace std;
int dp[1000];
int p(int v,int*a,int size){
	if(v<=0)return 0;
	for(int i=0;i<size;i++){
		if(v>=a[i]){
			if(dp[v-a[i]]==inf)dp[v-a[i]]=p(v-a[i],a,size);
				dp[v] = min(dp[v-a[i]]+1,dp[v]); 
		}
		else break;
	}
	//printf("dp[%d]=%d\n",v,dp[v]);
	return dp[v];
} 
int getMax(int *a,int size,int k){
	for(int v=1;;v++){
		if(p(v,a,size)>k)return v-1;
	}
}
int main(){
	
	int size;
	cin>>size;
	int *a = new int[size]();
	for(int i=0;i<size;i++){
		cin>>a[i]; 
	}
	for(int i=0;i<1000;i++){
	dp[i]=inf;
	}//初始化动态数组,取inf是为了标志此项未被赋过值,因此需要继续递归下去 
	
	//构建邮票票值数组 
	int k;//取的邮票张数 
	cin>>k;
	cout<<getMax(a,size,k);
    return 0;
}


猜你喜欢

转载自blog.csdn.net/qhlpptdyfn/article/details/80400639