POJ_1787解题报告

第一次写——

题意不再复述,(最近我一直在读题上犯错误..丢人)

明显的模型就是多重背包。注意了自己程序细节问题就很简单。

时间卡的紧一些,就用背包九讲上的01背包优化吧,可能是打印路径这里处理的不好,有500多ms

下次试试用单调队列优化。。


#include"stdio.h"
#include"stdlib.h"
#include"time.h"
#include"math.h"
#include"iostream"
#include"string.h"
#include"algorithm"
#include"vector"
#include"string"
#include"queue"
#include"map"

#define nmax 10000
#define vmax 11000
#define inf 0x7ffffff
#define eps 1e-8
#define PI 3.1415926535
#define PRIME 9999991
using namespace std;
int P;
int dp[vmax];
struct Pr{
    int i,k;
    int prv;
}pre[vmax];
int c[5];
int price[5];
///vars

void init_dp(){
    int i;
    for(i=0;i<=P;i++){
        dp[i]=-inf;
    }
}
inline int miny(int a,int b){return a<b?a:b;}

int main(){

    //freopen("d:\\testdata.txt","r",stdin);
    //freopen("d:\\spout1.txt","w",stdout);
    //价格们:
    price[0]=1;
    price[1]=5;
    price[2]=10;
    price[3]=25;
    while(scanf("%d%d%d%d%d",&P,&c[0],&c[1],&c[2],&c[3])==5&&P){
        if(c[0]>=P){//小剪枝,没太大用
            printf("Throw in %d cents, %d nickels, %d dimes, and %d quarters.\n",P,0,0,0);
            continue;
        }

        init_dp();
        memset(pre,0,sizeof(pre));//指向上一个决策的数组

        dp[0]=0;
        int i,vi;
        for(i=0;i<4;i++){//四种物品,i代表前i种
            if(c[i]*price[i]>=P){
                for(vi=price[i];vi<=P;vi++){
                    if(dp[vi]<dp[vi-price[i]]+1){
                        dp[vi]=dp[vi-price[i]]+1;
                        pre[vi].i=i;
                        pre[vi].k=1;
                        pre[vi].prv=vi-price[i];
                    }
                }
            }
            else{
                int k;
                for(k=1;k<=c[i];k<<=1){
                    c[i]-=k;
                    int costi=price[i]*k;
                    int vali=k;
                    for(vi=P;vi>=costi;vi--){
                        if(dp[vi]<dp[vi-costi]+vali){
                        dp[vi]=dp[vi-costi]+vali;
                        pre[vi].i=i;
                        pre[vi].k=vali;
                        pre[vi].prv=vi-costi;
                        }
                    }
                    //printf("k=%d ",k);
                }

                    int costi=price[i]*c[i];
                    int vali=c[i];
                    for(vi=P;vi>=costi;vi--){
                        if(dp[vi]<dp[vi-costi]+vali){
                        dp[vi]=dp[vi-costi]+vali;
                        pre[vi].i=i;
                        pre[vi].k=vali;

                        pre[vi].prv=vi-costi;
                        }
                    }

            }
            //if(dp[P]>0){break;}//这句话千万不能加。。。我当时犯傻了
        }
        int n[5];
        memset(n,0,sizeof(n));
        if(dp[P]>0){//数路径上的各种硬币用了多少个
            int pi=P;
            while(pi){
                n[pre[pi].i]+=pre[pi].k;
                
                pi=pre[pi].prv;
            }
            printf("Throw in %d cents, %d nickels, %d dimes, and %d quarters.\n",n[0],n[1],n[2],n[3]);
        }
        else
        printf("%s\n","Charlie cannot buy coffee.");
    }


return 0;}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值