uva242,Stamps and Envelope Size

这题紫薯上翻译错了

应该是:如果有多个并列,输出邮票种类最少的那个,如果还有并列,输出最大面值最小的那个

坑了我一个下午

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("
");
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/acbingo/p/4314022.html