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