嗯總算開始寫今天的日記
今天似乎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.