这题紫薯上翻译错了
应该是:如果有多个并列,输出邮票种类最少的那个,如果还有并列,输出最大面值最小的那个
坑了我一个下午
dp[p][q]==1表示可以用不超过q张组成面额p
结合记忆化,p从1开始枚举,一直枚举找到dp[p][q]=0的时候就可以了
这题应该归类成一种背包吧
注意dp初始化的时候应该初始化为-1(我就因为粗心,tle好久)
最后输出的时候比较恶心
最终的修改后的代码
实验证明,先读入所有数据后再处理比边读数据边处理要快
/* * Author: Bingo * Created Time: 2015/3/4 13:54:40 * File Name: uva242.cpp */ #include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> #include <string> #include <vector> #include <stack> #include <queue> #include <set> #include <time.h> using namespace std; const int maxint = 1000000; int S,T,n; int map[20][20]; int dp[1200][20]; //int ans[20][20]; int ans,ans_num,ans_max,ans_case; int fun(int p,int q,int c){ if (dp[p][q]!=-1) return dp[p][q]; else if (p==0){ dp[p][q]=1; return 1; }else if (q==0) { dp[p][q]=0; return 0; }else { for (int i=1;i<=map[c][0];i++) { if (p>=map[c][i]&&fun(p-map[c][i],q-1,c)){ dp[p][q]=1; return 1; } } } dp[p][q]=0; return 0; } int cmp(int a,int b){//比较最大连续邮资相同的集合 if(map[a][0]<map[b][0])return a; if(map[b][0]<map[a][0])return b; for(int i=map[a][0];i>0;i--){ if(map[a][i]<map[b][i])return a; if(map[b][i]<map[a][i])return b; } return a; } int main(){ while (cin>>S&&S){ cin>>T; int mycase=0; ans=0;ans_num=maxint;ans_max=maxint; while (T--){ cin>>n; mycase++; memset(dp,-1,sizeof(dp)); map[mycase][0]=n; for (int i=1;i<=n;i++) { cin>>map[mycase][i]; } int p; for (p=1;;p++) { if (fun(p,S,mycase)==0) break; } int t=p-1; if (t>ans){ ans=t; ans_case=mycase; }else if (t==ans){ ans_case=cmp(mycase,ans_case); } } printf("max coverage =%4d :", ans); for(int i=1;i<=map[ans_case][0];i++){ printf("%3d",map[ans_case][i]); } printf("\n"); } return 0; }