September 17th 模拟赛PJ T4 稀有逛超市 Solution

空降题目处(外网)
点我点我点我

空降题目处(内网)
点我点我点我

Description

【题目背景】
众所周知,机房里有三个人,一个是 THU 的,一个是 PKU 的,最弱的是 FDU 的。稀有就 是那个 FDU 的„稀有特别喜欢吃东西,但是又喜欢打游戏„结果就忙得不可开交„
【问题描述】
稀有打算去超市买点东西,他身上共有 N 元钱,其中 K 元钱都是准备用来买游戏打的, 因此十分蛋疼的就是剩下的钱安排买什么了。超市的每件东西有很多类,第一类只有价格和 给稀有带来的愉悦值,但是每种只有一件;第二类每种有无数件,同样有价格和愉悦值;其 他类除了每一种有价格和愉悦值之外,每一类一共只能取一件。(我会告诉你稀有去了 HZ 之后身上没钱了?)

Input

输入文件 shop.in 共有 M+1 行。
第一行包含三个整数,N,K,M,N,K 如题意,M 为东西个数。
第二至 M+1 行包含三个正整数,分别表示价格 Pi,愉悦值 Wi,属于哪一类 Ci。

Output

输出文件 shop.out 只有一行,最大愉悦值。

Solution

典型的DP问题,不用考虑时间,只用优化第2类,详见Code(以C++版为准).

Code

C++

#include<fstream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;

int ans,n,m,k,d[1001][1001][2],tot[1001],e[20001],f[20001];

int main()
{
    freopen("shop.in","r",stdin);
    freopen("shop.out","w",stdout);
    int _;
    scanf("%d%d%d",&n,&_,&m);
    n-=_;
    int x,y,z;
    for (int i=1;i<=m;i++)
    {
        scanf("%d%d%d",&x,&y,&z);
        d[z][++tot[z]][0]=x;
        d[z][tot[z]][1]=y;
    }
    memset(f,-40000,sizeof(f));
    f[n]=0;
    for (int i=1;i<=1;i++)
    {
        for (int j=1;j<=tot[i];j++)
        {
            for (int k=0;k<=n-1;k++)
            {
                f[k]=max(f[k],f[k+d[i][j][0]]+d[i][j][1]);
                ans=max(ans,f[k]);
            }
        }
    }
    for (int i=2;i<=2;i++)
    {
        for (int j=1;j<=tot[i];j++)
        {
            for (int k=n-d[i][j][0];k>=0;k--)
            {
                f[k]=max(f[k],f[k+d[i][j][0]]+d[i][j][1]);
                ans=max(ans,f[k]);
            }
        }
    }
    for (int i=3;i<=1000;i++)
    {
        memcpy(e,f,sizeof(f));
        for (int j=1;j<=tot[i];j++)
        {
            for (int k=0;k<=n-1;k++)
            {
                f[k]=max(f[k],e[k+d[i][j][0]]+d[i][j][1]);
                ans=max(ans,f[k]);
            }
        }
    }
    printf("%d\n",ans);
}

Pascal

uses math;
var
        i,j,k,n,v,ans,tt,ma:longint;
        f:array[0..20000,1..2] of longint;
        a:array[1..1000,1..2] of longint;
        t:array[1..1000,0..1000] of longint;
begin
        assign(input,'shop.in'); reset(input);
        assign(output,'shop.out'); rewrite(output);
        readln(v,k,n);
        v:=v-k;
        for i:=1 to n do
        begin
                readln(a[i,1],a[i,2],tt);
                if tt>ma then ma:=tt;
                if tt>=3 then
                begin
                        inc(t[tt,0]);
                        t[tt,t[tt,0]]:=i;
                end
                else
                begin
                        if tt=1 then
                                for j:=v downto 0 do
                                begin
                                        if j-a[i,1]<0 then break;
                                        f[j,1]:=max(f[j,1],f[j-a[i,1],1]+a[i,2]);
                                end
                        else
                                for j:=0 to v do
                                begin
                                        if j-a[i,1]<0 then continue;
                                        f[j,1]:=max(f[j,1],f[j-a[i,1],1]+a[i,2]);
                                end;
                end;
        end;
        for i:=3 to ma do
        begin
                //for j:=v downto 0 do
                for k:=1 to t[i,0] do
                begin
                        //for k:=1 to t[i,0] do
                        for j:=v downto 0 do
                        begin
                                if j<a[t[i,k],1] then break;
                                f[j,2]:=max(f[j,2],f[j-a[t[i,k],1],1]+a[t[i,k],2]);
                        end;
                end;
                for k:=0 to v do
                f[k,1]:=max(f[k,1],f[k,2]);

        end;
        writeln(f[v,1]);
        close(input);
        close(output);
end.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值