UVa242Stamps and Envelope Size

来源:互联网 发布:qq分享组件js代码 编辑:程序博客网 时间:2024/04/27 01:57

        题意:信封上最多贴S张邮票。有N个邮票集合,每个集合有不同的面值。问哪个集合的最大连续邮资最大,输出最大连续邮资和集合元素。最大连续邮资是用S张以内邮票面值凑1,2,3...到n+1凑不出来了,最大连续邮资就是n。如果不止一个集合结果相同,输出集合元素少的,如果仍相同,输出最大面值小的。

        思路:DP。DP[i][j]。i表示需要的邮资,j表示可用邮票数,数组存的是bool类型值,表示能否凑出。如果存在DP[i-某种面值][j-1]为真,那么DP[i][j]为真。下面是记忆化搜索的代码。


#include <iostream>#include <stdio.h>#include <cmath>#include <algorithm>#include <iomanip>#include <cstdlib>#include <string>#include <memory.h>#include <vector>#include <queue>#include <stack>#include <ctype.h>#define INF 1000000using namespace std;int stamp[12][12];int DP[1110][12];bool fun(int set,int c,int n){if(DP[c][n]!=-1)return DP[c][n];if(!c){DP[c][n]=true;return true;}if(!n){DP[c][n]=false;return false;}for(int i=1;i<=stamp[set][0];i++){if(c>=stamp[set][i]&&fun(set,c-stamp[set][i],n-1)){DP[c][n]=true;return true;}}DP[c][n]=false;return false;}int cmp(int a,int b){//比较最大连续邮资相同的集合 if(stamp[a][0]<stamp[b][0])return a;if(stamp[b][0]<stamp[a][0])return b;for(int i=stamp[a][0];i>0;i--){if(stamp[a][i]<stamp[b][i])return a;if(stamp[b][i]<stamp[a][i])return b;}return a;}int main(){int s;while(cin>>s){if(!s)break;int N;cin>>N;int ans=0;int key=0;for(int i=1;i<=N;i++){cin>>stamp[i][0];for(int j=1;j<=stamp[i][0];j++){cin>>stamp[i][j];}}for(int i=1;i<=N;i++){memset(DP,-1,sizeof(DP));int k=0;for(int j=1;;j++){if(fun(i,j,s)){k=j;}else{break;}}if(k==ans){key=cmp(key,i);}if(k>ans){ans=k;key=i;}}printf("max coverage =%4d :",ans);for(int i=1;i<=stamp[key][0];i++){printf("%3d",stamp[key][i]);}printf("\n");}return 0;}


0 0
原创粉丝点击