这一节开始涉及搜索了, 练练很好,还好以前做过,要不然又要被猥琐到了,不过做这一节也花的时间比前面多很多
----------------------------------------------------------美丽的分界线----------------------------------------------------------
USACO 1.4.1 Packing Rectangles 铺放矩形块
ws题,直接将以前编的程序,改了改的,如果比赛有这种题,那我放弃吧。
ms有一年noip第3题是模拟,也是一道ws题,好像叫作业调度吧....
这题简单叙述:找出一个面积最小的矩形,可以将4个矩形块放在这个矩形中而不互相重叠,还需要找出面积最小的矩形的长宽方案数,并输出。
我直接暴力...
program packrec(input,output);
var
total,i,j,m,n,s1,s2,s3,s4,d1,d2,d3,d4:longint;
s,d,x,y:array[1..4] of longint;
f:array[1..4,1..2] of longint;
ans:array[1..20,1..2] of longint; //最小矩形的长宽
procedure init;
begin
assign(input,'packrec.in');
assign(output,'packrec.out');
reset(input);
rewrite(output);
end;
procedure outit;
begin
close(input);
close(output);
end;
procedure swap(var x,y:longint);
var
temp:longint;
begin
temp:=x;
x:=y;
y:=temp;
end;
function max(a,b:longint):longint;
begin
if a>b then max:=a
else max:=b;
end;
Procedure work(a,b:longint); //找出最小面积,并记录最小面积的其他方案
var
i:longint;
begin
if a>b then swap(a, b);
if a*b<ans[1,1]*ans[1,2] then
begin
total:=1;
ans[1,1]:=a;
ans[1,2]:=b;
end;
if a*b=ans[1,1]*ans[1,2] then
begin
for i:=1 to total do
if (a=ans[i,1])and(b=ans[i,2]) then
exit;
inc(total);
ans[total,1]:=a;
ans[total,2]:=b;
end;
end;
begin
init;
for i:=1 to 4 do readln(f[i,1],f[i,2]);
total:=1;
ans[1,1]:=maxint;
ans[1,2]:=maxint;
for s1:=1 to 4 do //枚举4个矩形所有的排列
for s2:=1 to 4 do
for s3:=1 to 4 do
for s4 :=1 to 4 do
if [s1,s2,s3,s4]=[1..4] then
for d1:=1 to 2 do //枚举矩形横放还是竖放
for d2:=1 to 2 do
for d3:=1 to 2 do
for d4:=1 to 2 do
begin
s[1]:=s1; s[2]:=s2; s[3]:=s3; s[4]:=s4;
d[1]:=d1; d[2]:=d2; d[3]:=d3; d[4]:=d4;
for i:=1 to 4 do
begin
x[i]:=f[s[i],d[i]];
y[i]:=f[s[i],3-d[i]];
end;
//根据题所给有6种基本方案,但其实4、5种是一样的,所以我这只有5种方案
//one
m:=x[1]+x[2]+x[3]+x[4];
n:=max(max(max(y[1],y[2]),y[3]),y[4]);
work(m,n);
//two
m:=max(x[1]+x[2]+x[3],x[4]);
n:=y[4]+max(max(y[1],y[2]),y[3]);
work(m,n);
//there
m:=max(x[1]+x[2],x[3])+x[4];
n:=max(max(y[3]+y[1],y[3]+y[2]),y[4]);
work(m,n);
//four
m:=x[1]+x[2]+max(x[3],x[4]);
n:=max(max(y[1],y[2]),y[3]+y[4]);
work(m,n);
//five
n:=max(y[1]+y[3],y[2]+y[4]);
if y[3]>=y[2]+y[4] then m:=max(max(x[1],x[2]+x[3]),x[3]+x[4]);
if (y[3]>y[4])and(y[3]<y[2]+y[4])then m:=max(max(x[1]+x[2],x[3]+x[4]),x[3]+x[2]);
if (y[3]<y[4])and(y[4]<y[1]+y[2])then m:=max(max(x[3]+x[4],x[1]+x[2]),x[1]+x[4]);
if y[4]>=y[1]+y[3] then m:=max(max(x[2],x[1]+x[4]),x[3]+x[4]);
if y[3]=y[4] then m:=max(x[1]+x[2],x[3]+x[4]);
work(m,n);
end;
for i:=1 to total-1 do
for j:=i+1 to total do
if ans[i,1]>ans[j,1] then
begin
swap(ans[i,1],ans[j,1]);
swap(ans[i,2],ans[j,2]);
end;
writeln(ans[1,1]*ans[1,2]);
for i:=1 to total do
writeln(ans[i,1],' ',ans[i,2]);
outit;
end.
USACO 1.4.2 The Clocks 时钟
dfs过的,不过有更厉害的算法,看不懂...(眼睛都花了)
program clocks(input,output);
const
q:array[1..9,1..9] of integer=((1,1,0,1,1,0,0,0,0),
(1,1,1,0,0,0,0,0,0),
(0,1,1,0,1,1,0,0,0),
(1,0,0,1,0,0,1,0,0),
(0,1,0,1,1,1,0,1,0),
(0,0,1,0,0,1,0,0,1),
(0,0,0,1,1,0,1,1,0),
(0,0,0,0,0,0,1,1,1),
(0,0,0,0,1,1,0,1,1));
var
bell,way,mean:array[1..9] of longint;
min,i,j:longint;
procedure init;
begin
assign(input,'clocks.in');
assign(output,'clocks.out');
reset(input);
rewrite(output);
end;
procedure outit;
begin
close(input);
close(output);
end;
function ok:boolean;
var
i:longint;
begin
for i:=1 to 9 do
if bell[i]<>0 then exit(false);
exit(true);
end;
procedure dfs(h,n:longint);
var
i,j:longint;
t:array[1..9] of longint;
begin
if n>=min then exit;
if ok then begin mean:=way;min:=n;exit;end;
if h=10 then exit;
t:=bell;
for i:=0 to 3 do
begin
way[h]:=i;
for j:=1 to 9 do bell[j]:=(t[j]+q[h,j]*i) mod 4;
dfs(h+1,n+i);
way[h]:=0;
end;
end;
begin
init;
for i:=1 to 9 do
begin
read(j);
bell[i]:=j div 3 mod 4;
if i mod 3=0 then readln;
end;
min:=maxlongint;
dfs(1,0);
for i:=1 to 9 do
while mean[i]<>0 do
if min<>1 then
begin
write(i,' ');
dec(mean[i]);
dec(min);
end
else
begin
writeln(i);
dec(mean[i]);
end;
outit;
end.
USACO 1.4.3 Arithmetic Progressions 等差数列
直接暴力,但必须粗中有细,因为容易超时,运算能减少的尽量减少,查找用O(1)的
program ariprog(input,output);
var
n,m,i,j,a,b,max,k:longint;
ok,ko:boolean;
squ:array[0..65000] of longint;
f:array[0..125000] of boolean; //双平方数最大125000
procedure init;
begin
assign(input,'ariprog.in');
assign(output,'ariprog.out');
reset(input);
rewrite(output);
end;
procedure outit;
begin
close(input);
close(output);
end;
begin
init;
readln(n);
readln(m);
for i:=0 to m do squ[i]:=sqr(i); //减少乘法运算
for i:=0 to m do
for j:=0 to m do
f[squ[i]+squ[j]]:=true;
max:=sqr(m)*2;j:=0;
for i:=0 to max do
if f[i] then
begin
inc(j);
squ[j]:=i;
end;
ko:=true;
for b:=1 to max div (n-1) do
for a:=1 to j do
if squ[a]+(n-1)*b<=max then //判断第N个数是否超过双平方数最大的数,减少运算
begin
ok:=true;
for k:=1 to n-1 do
if f[squ[a]+k*b]=false then
begin
ok:=false;
break;
end;
if ok then
begin
writeln(squ[a],' ',b);
ko:=false;
end;
end;
if ko then writeln('NONE');
outit;
end.
USACO 1.4.4 Mother's Milk 母亲的牛奶
dfs过掉,USACO还有用DP的,不够判断也挺多的,
program milk3(input,output);
var
n,i,a1,b1,c1:longint;
f:array[0..20] of boolean;
h:array[0..20,0..20,0..20] of boolean;
procedure init;
begin
assign(input,'milk3.in');
assign(output,'milk3.out');
reset(input);
rewrite(output);
end;
procedure outit;
begin
close(input);
close(output);
end;
procedure dfs(a,b,c:longint);
begin
if h[a,b,c] then exit;
h[a,b,c]:=true;
if a=0 then
if f[c]=false then begin f[c]:=true;inc(n);end;
if a>0 then //如果a不是空的,则倒入其他两桶
begin
if b<b1 then
if a+b>b1 then dfs(a+b-b1,b1,c)
else dfs(0,a+b,c);
if c<c1 then
if a+c>c1 then dfs(a+c-c1,b,c1)
else dfs(0,b,a+c);
end;
if b>0 then //如果b不是空的,则倒入其他两桶
begin
if a<a1 then
if a+b>a1 then dfs(a1,a+b-a1,c)
else dfs(a+b,0,c);
if c<c1 then
if b+c>c1 then dfs(a,b+c-c1,c1)
else dfs(a,0,b+c);
end;
if c>0 then //如果c不是空的,则倒入其他两桶
begin
if a<a1 then
if a+c>a1 then dfs(a1,b,a+c-a1)
else dfs(a+c,b,0);
if b<b1 then
if b+c>b1 then dfs(a,b1,b+c-b1)
else dfs(a,b+c,0);
end;
end;
begin
init;
readln(a1,b1,c1);
dfs(0,0,c1);
for i:=0 to 20 do
if f[i] then
begin
if n=1 then begin writeln(i);break;end;
write(i,' ');
dec(n);
end;
outit;
end.