t1
在一个长方型框子里,最多有N(0≤N≤6)个相异的点。在其中任何一个点上放一个很小的油滴,那么这个油滴会一直扩展,直到接触到其它油滴或者框子的边界。必须等一个油滴扩展完毕才能放置下一个油滴。那么应该按照怎样的顺序在这N个点上放置油滴,才能使放置完毕后所有油滴占据的总体积最大呢?(不同的油滴不会相互融合)
注:圆的面积公式V=pi*r*r,其中r为圆的半径。
事实上,这是一道水题。。。。。。但不知为何,我就是没过。。。。。。
看到这个小得人神共愤的n,不解释,果断暴力,6!而已,不会时超,属于送分题。
*
特别感谢郑宇轩大佬的支持!!!
*
t2
虽然msh长大了,但她还是很喜欢找点游戏自娱自乐。有一天,她在纸上写了一串数字:1,1,2,5,4。接着她擦掉了一个1,结果发现剩下1,2,4都在自己所在的位置上,即1在第1位,2在第2位,4在第4位。她希望擦掉某些数后,剩下的数列中在自己位置上的数尽量多。她发现这个游戏很好玩,于是开始乐此不疲地玩起来……不过她不能确定最多能有多少个数在自己的位置上,所以找到你,请你帮忙计算一下!
对于20%的数据,n<=20;
对于60%的数据,n<=100;
对于100%的数据,n<=1000.
刚看题的时候一脸懵逼,不知如何下手,先打了个暴力,然后再慢慢想。
苦想一个多小时,终于想出了dp的方法,高兴无比的交了上去,结果10分。。。。。。还不如交暴力
此题,n^2能过,n^3不能过,没有后效性,很明显是n^2的dp。
f[0,0]:=0;
for i:=1 to n do
begin
for j:=1 to i do
begin
if a[i]=j then s:=1
else s:=0;
f[i,j]:=max(f[i-1,j-1]+s,f[i-1,j]);
end;
end;
for i:=1 to n do
if f[n,i]>ans then ans:=f[n,i];
writeln(ans);
设f[i,j]表示到第i个数之前,共删除j个数所能得到的符合条件的数的个数,然后转移即可。
t3
一个软件开发公司同时要开发两个软件,并且要同时交付给用户,现在公司为了尽快完成这一任务,将每个软件划分成m个模块,由公司里的技术人员分工完成,每个技术人员完成同一软件的不同模块的所用的天数是相同的,并且是已知的,但完成不同软件的一个模块的时间是不同的,每个技术人员在同一时刻只能做一个模块,一个模块只能由一个人独立完成而不能由多人协同完成。一个技术人员在整个开发期内完成一个模块以后可以接着做任一软件的任一模块。写一个程序,求出公司最早能在什么时候交付软件。
也是dp,不过比赛的时候我专注于第二题,后面两题基本没想,所以第二题一挂就崩盘了,下次一定要注意时间分配。
对于这类问题,我们可以转为判定性问题,即在1~1000中二分一个mid,再判断是否可以在mid天内完成。
ll:=1;
rr:=1000;
mid:=(ll+rr) div 2;
while ll<rr do
begin
fillchar(f,sizeof(f),0);
f[0,0,0]:=1;
for i:=1 to n do
begin
for j:=0 to m do
for l:=0 to j do
if l*a[i]<=mid then
begin
r:=(mid-l*a[i]) div b[i];
for k:=0 to m do
begin
t:=r;
if t>k then t:=k;
if f[i-1,j-l,k-t]=1 then
f[i,j,k]:=1;
end;
end;
end;
if f[n,m,m]=0 then
begin
ll:=mid+1;
mid:=(ll+rr) div 2;
end
else
begin
rr:=mid;
ans:=mid;
mid:=(ll+rr) div 2;
end;
end;
f[i,j,k]表示用到第i个人,第一个项目做了j块,第二个项目做了k块,是否能在mid天内完成。
t4
Black Box是一种原始的数据库。它可以储存一个整数数组,还有一个特别的变量 i 。最开始的时候Black Box是空的,而 i 等于 0。这个 Black Box 要处理一串命令。
命令只有两种:
ADD(x): 把 x 元素放进 Black Box;
GET: i 加 1 ,然后输出 Black box 中第 i 小的数。
记住:第 i 小的数,就是 Black Box里的数的按从小到大的顺序排序后的第 i 个元素。
例如 !
我们来演示一下一个有11个命令的命令串。
现在要求找出对于给定的命令串的最好的处理方法。ADD 和 GET 命令分别最多有200000个。
现在用两个整数数组来表示命令串:
1. A(1), A(2), …, A(M): 一串将要被放进Black Box的元素。每个数都是绝对值不超过2000000000的整数,M <=200000。例如上面的例子就是A=(3, 1, -4, 2, 8, -1000, 2).
2. u(1), u(2), …, u(N): 表示第u(j)个元素被放进了Black Box里后就出现一个GET命令。例如上面的例子中u=(1, 2, 6, 6)。 输入数据不用判错。
对于30%的数据,M<=10000;
对于50%的数据,M<=100000;
对于100%的数据,M<=200000。
看上去很难,但实际上可以用很暴力的方法解决。。。。。。
建两个堆a,b,a为大根堆,b为小根堆。b储存当前读入的数中前i小的数, a储存其它的数,如何维护我就不说了
```var
max,min:array[0..400001]of longint;
nowl,now,n,m,i,j:longint;
x,y,a,b:array[0..400001]of longint;
procedure add(x:longint);
var
no,i,t:longint;
begin
inc(b[0]);
b[b[0]]:=x;
no:=b[0];
while (no>1)and(b[no]<b[no div 2]) do
begin
t:=b[no];
b[no]:=b[no div 2];
b[no div 2]:=t;
no:=no div 2;
end;
end;
procedure downa;
var
no,t,k:longint;
begin
no:=1;
while (no*2<=a[0])and((a[no]<a[no*2])or(a[no]<a[no*2+1])) do
begin
t:=no*2;
if no*2+1<=a[0] then
begin
if a[t]<a[no*2+1] then
t:=no*2+1;
end;
if a[t]>a[no] then
begin
k:=a[t];
a[t]:=a[no];
a[no]:=k;
no:=t;
end;
end;
end;
procedure upa;
var
no,k:longint;
begin
no:=a[0];
while (no>1)and(a[no]>a[no div 2]) do
begin
k:=a[no];
a[no]:=a[no div 2];
a[no div 2]:=k;
no:=no div 2;
end;
end;
procedure downb;
var
no,t,k:longint;
begin
no:=1;
while((no*2<=b[0])and(b[no]>b[no*2]))or((b[no]>b[no*2+1])and(no*2+1<=b[0])) do
begin
t:=no*2;
if no*2+1<=b[0] then
begin
if b[t]>b[no*2+1] then
t:=no*2+1;
end;
if b[t]<b[no] then
begin
k:=b[t];
b[t]:=b[no];
b[no]:=k;
no:=t;
end;
end;
end;
procedure get;
var
i,t,k:longint;
begin
while ((b[1]<a[1])and(b[0]>0))or(b[0]>nowl-now) do
begin
inc(a[0]);
a[a[0]]:=b[1];
b[1]:=b[b[0]];
b[b[0]]:=0;
dec(b[0]);
upa;
downb;
end;
while a[0]>now do
begin
add(a[1]);
a[1]:=a[a[0]];
a[a[0]]:=0;
dec(a[0]);
downa;
end;
writeln(a[1]);
end;
begin
fillchar(a,sizeof(a),0);
fillchar(b,sizeof(b),0);
readln(m,n);
for i:=1 to m do
read(x[i]);
readln;
for i:=1 to n do
read(y[i]);
y[0]:=0;
for i:=1 to n do
begin
inc(now);
for j:=y[now-1]+1 to y[now] do
begin
inc(nowl);
add(x[j]);
end;
get;
end;
end.