Stamps and Envelope Size UVA - 242

动态规划的思想,dp[i][j]其中i代表剩余的需要“填充”的资金的数量、j代表着剩余的可以使用的邮票的数量,如果当前放入的邮票的面值为a,那么如果dp[i-a][j-1]为真,则dp[i][j]就肯定为真,如果放入该邮票之后i-a为0,那么dp[i-a][j-1]就肯定为真,如果j-1为0同时i-a不为0,说明当前的放置方法不能将资金全部“填充”,则dp[i][j]就为假,如果i-a以及j-1均不为0,那么就枚举+递归,继续判断是否存在一种放置方法使得在现有的可放置的邮票数量内“填充”完所有的资金,具体实现见如下代码:

package a;//实际提交的时候记得去掉包名

import java.util.Arrays;
import java.util.Scanner;

public class Main {

    int S,N;
    int[][] stamp=new int[12][12];
    int[][] dp=new int[1010][12];
    int ans,key;

    public void Init(){
        for(int i=0;i<1010;i++)
            Arrays.fill(dp[i],-1);
    }

    public boolean DP(int i,int j,int s){
        if(dp[j][s]!=-1){
            if(dp[j][s]==0) return false;
            else return true;
        }
        if(j==0){
            dp[j][s]=1;
            return true;
        }
        if(s==0){
            dp[j][s]=0;
            return false;
        }
        for(int k=1;k<=stamp[i][0];k++){
            if(j>=stamp[i][k]&&DP(i,j-stamp[i][k],s-1)){
                dp[j][s]=1;
                return true;
            }
        }
        dp[j][s]=0;
        return false;
    }

    public int judge(int a,int b){
        if(stamp[a][0]<stamp[b][0]) return a;
        if(stamp[a][0]>stamp[b][0]) return b;
        for(int ind=stamp[a][0];ind>=0;ind--){
            if(stamp[a][ind]<stamp[b][ind]) return a;
            if(stamp[a][ind]>stamp[b][ind]) return b;
        }
        return a;
    }

    public void Solve(){
        Scanner scan=new Scanner(System.in);
        while(scan.hasNext()) {
            S=scan.nextInt();
            if(S==0) break;
            N=scan.nextInt();
            for(int i=0;i<N;i++){
                stamp[i][0]=scan.nextInt();
                for(int j=1;j<=stamp[i][0];j++){
                    stamp[i][j]=scan.nextInt();
                }
            }
            ans=-1;
            for(int i=0;i<N;i++){
                int record=0;
                Init();
                for(int j=1;;j++){
                    if(DP(i,j,S)){
                        record=j;
                    }
                    else break;
                }

                if(record==ans){
                    key=judge(key,i);
                }
                if(record>ans){
                    key=i;
                    ans=record;
                }
            }
            System.out.printf("max coverage =%4d :",ans);
            for(int i=1;i<=stamp[key][0];i++){
                System.out.printf("%3d",stamp[key][i]);
            }
            System.out.println();
        }
    }

    public static void main(String[] args){
        Main a=new Main();
        a.Solve();
    }

}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值