空降题目处(外网)
点我点我点我
空降题目处(内网)
点我点我点我
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.