金组刷不动,滚回来刷银组TAT
[题面描述]
J有n块田,在一条直线上,田里有b种牛,每种牛的都有自己的叫声大小vi,由于有风,每块田可以听到的叫声大小为田里所有牛的叫声和加左边的叫声大小减一(最左边那块田的话,则只能听到自己田地里的声音),给定每种牛的叫声大小已及每块田所听到的声音,求最小可能存在多少头牛,没有解输出-1
翻译的不是很好啊。。不过也可以看。。(虽然漏了点条件。。。)
很明显的背包
f[i]表示要这块田总叫声为i的最小花费。。
无限背包一下。。
然后对于每一块田,d[i]-(d[i-1]-1)就是它自己的叫声
然后ans+=就好了..
因为总叫声小于10^5
所以O(10^5*B+n)
比较奇葩的复杂度。。
Code:
const shuru='mooo.in';
shuchu='mooo.out';
maxn=101;
INF=1 shl 27;
sound=100000;
var d,w:array[0..maxn] of longint;
f:array[0..sound] of longint;
b,tot,ans,i,j,k,n:longint;
procedure init;
begin
readln(n,b);
for i:=1 to b do readln(w[i]);
for i:=1 to n do readln(d[i]);
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 sound do f[i]:=INF;
for i:=1 to b do
for j:=w[i] to sound do
f[j]:=min(f[j],f[j-w[i]]+1);
d[0]:=1;
for i:=1 to n do
begin
inc(ans,f[d[i]-(d[i-1]-1)]);
if d[i]=0 then d[i]:=1;
end;
if ans>=INF then writeln(-1)
else writeln(ans);
end;
begin
main;
end.
一次AC..