嗯总算开始写今天的日记
今天似乎DP专场?
1. 采药(medic.pas/c/cpp)
【问题描述】
辰辰是个天资聪颖的孩子,他的梦想是成为世界上最伟大的医师。为此,他想拜附近最有威望的医师为师。医师为了判断他的资质,给他出了一个难题。医师把他带到一个到处都是草药的山洞里对他说:“孩子,这个山洞里有一些不同的草药,采每一株都需要一些时间,每一株也有它自身的价值。我会给你一段时间,在这段时间里,你可以采到一些草药。如果你是一个聪明的孩子,你应该可以让采到的草药的总价值最大。”
如果你是辰辰,你能完成这个任务吗?
【输入】
输入的第一行有两个整数n和m,用一个空格隔开。m代表总共能够用来采药的时间,n代表山洞里的草药的数目。接下来的n行每行包括两个整数,分别表示采摘某株草药的时间Ti和这株草药的价值Vi。
【输出】
输出包括一行,这一行只包含一个整数,表示在规定的时间内,可以采到的草药的最大总价值。
刚开始看到的时候激动了下
【数据规模】
对于 50%的数据,n,m≤1000;
对于 100%的数据,n,m≤100000,Ti,Vi≤10。
= =!
然后看到了ti,vi
多重揹包
我加了点贪心优化
const shuru='medic.in';
shuchu='medic.out';
var hash:Array[0..11,0..11] of longint;
w,v:array[0..100001] of longint;
f:Array[0..100001] of longint;
m,num,x,y,i,j,k,n,ans:longint;
procedure get(x,y,bei,mi:longint);
begin
if bei=0 then exit;
if bei>mi then begin
inc(num);
w[num]:=x*mi; v[num]:=y*mi;
get(x,y,bei-mi,mi*2);
end;
if bei<=mi then begin
inc(num);
w[num]:=x*bei; v[num]:=y*bei;
end;
end;
procedure init;
begin
assign(input,shuru);
assign(output,shuchu);
reset(input);
rewrite(output);
readln(n,m);
for i:=1 to n do
begin
readln(x,y);
inc(hash[x,y]);
end;
for j:=10 downto 6 do
while hash[1,j]>0 do
begin
if m>=hash[1,j] then begin
m:=m-hash[1,j];
inc(ans,j*hash[1,j]);
hash[1,j]:=0;
end
else begin
hash[1,j]:=hash[1,j]-m;
inc(ans,m*j);
m:=0;
end;
if m=0 then break;
end;
for i:=1 to 10 do
for j:=1 to 10 do
get(i,j,hash[i,j],1);
close(input);
end;
function max(a,b:longint):longint;
begin
if a>b then exit(a);
exit(b);
end;
procedure main;
begin
init;
for i:=1 to num do
for j:=m downto w[i] do
f[j]:=max(f[j],f[j-w[i]]+v[i]);
writeln(f[m]+ans);
close(output);
end;
begin
main;
end.
ps.标程写错害的我找了好久的错2. 方格取数(matrix.pas/c/cpp)
【问题描述】
给定一个 n×m 的矩阵,记录左上角为(1,1),右下角为(n,m),现在从(1,1)开始取数,每次只
能向下或向右移动一个单位,最终到达(n,m),我们把路径上所有的数相乘,结果记为C。使C 的结
果最大已经不能满足我们了,现在我们想让C 末尾的零个数最少。
PS. 11000 末尾有三个零,100000100 末尾有两个零。
【输入】
第一行是两个正整数 n 和m,表示矩阵大小。
接下来 n 行每行m 个正整数,给出了整个矩阵。
【输出】
一个整数:最少的零的个数。
最开始想到了求2,5个数最小的。。然后认为错的就cha掉,,结果一直没想出来
其实就是找2个数最少的路和5个数最小的路
取他们之中最小的那个
没错我就是智商拙计的吴瑾昭
const shuru='matrix.in';
shuchu='matrix.out';
var f,g,a,b:Array[0..1001,0..1001] of longint;
x,y,n,m,i,j,k:longint;
procedure init;
begin
assign(input,shuru);
assign(output,shuchu);
reset(input);
rewrite(output);
readln(n,m);
for i:=1 to n do
for j:=1 to m do
begin
read(X);
y:=x;
while (y and 1=0) do
begin
inc(a[i,j]);
y:=y shr 1;
end;
y:=x;
while (y mod 5=0) do
begin
inc(b[i,j]);
y:=y div 5;
end;
end;
close(input);
for i:=2 to n do
begin
f[0,i]:=1 shl 25;
f[i,0]:=1 shl 25;
g[i,0]:=1 shl 25;
g[0,i]:=1 shl 25;
end;
end;
function min(a,b:longint):longint;
begin
if a<b then exit(A);
exit(B);
end;
procedure main;
begin
init;
for i:=1 to n do
for j:=1 to m do
begin
f[i,j]:=min(f[i-1,j],f[i,j-1])+a[i,j];
g[i,j]:=min(g[i-1,j],g[i,j-1])+b[i,j];
end;
writeln(min(f[n,m],g[n,m]));
close(output);
end;
begin
main;
end.
3. 统计(count.pas/c/cpp)
【问题描述】
对于排列(P1,P2,P3,…Pn),定义(i,j)为逆序对当且仅当i<j 且Pi>Pj。统计{1,2,3,…,n}
的所有排列中,逆序对数量为m 的排列个数。
刚开始傻傻的以为是数学题。。就去找规律
然后发现是DP。。
设f[i,j]是1..i有j个逆序对的排列个数
f[i,j]=f[i-1,j-1]+f[i-1,j-2]+...f[i,j-(i-1)]
用前缀和优化一下O(n^2)
Code:
const shuru='count.in';
shuchu='count.out';
var s,f:array[0..1001,-10..1001] of int64;
m,i,j,k,n:longint;
procedure init;
begin
assign(input,shuru);
assign(output,shuchu);
reset(input);
rewrite(output);
readln(n,m);
close(input);
for i:=1 to n do
begin
s[i,0]:=1;
s[i,-1]:=0;
f[i,0]:=1;
end;
s[1,1]:=1;
end;
Function max(a,b:longint):longint;
begin
if a>b then exit(a);
exit(b);
end;
Function min(a,b:longint):longint;
begin
if a<b then exit(a);
exit(B);
end;
procedure main;
begin
init;
for i:=2 to n do
begin
for j:=1 to min(m,i*(i-1) div 2) do
begin
f[i,j]:=(s[i-1,j]-s[i-1,max(-1,j-i)]) mod 1234567;
end;
for j:=1 to m do
s[i,j]:=s[i,j-1]+f[i,j];
end;
writeln(f[n,m]);
close(output);
end;
begin
main;
end.