Usaco1.3 我的程序和题解

http://hi.baidu.com/mfs666/blog/item/4cab5ceef2c055fdb2fb9594.html

 

usaco1.3 貌似主题是贪心和简单搜索

1.3.1

Mixing Milk (milk)

最显著的贪心,先排序(快排),每次都加入最多的价钱最低的牛奶,直到加满

code

{
ID: mfs.dev2
PROG: milk
LANG: PASCAL
}


program milk;

type
p=record
   v,a:longint;
end;

var
n,m,i,d,r,t:longint;
o:array[0..5000] of p;

procedure quicksort(s,t:longint);
var
   i,j,q:longint;
   t1:p;
begin
   i:=s; j:=t; q:=o[(i+j) div 2].v;
   repeat
    while (o[i].v<q) do inc(i);
    while (o[j].v>q) do dec(j);
    if (i<=j) then begin
     t1:=o[i]; o[i]:=o[j]; o[j]:=t1;
     inc(i); dec(j);
     end;
   until i>j;
   if (s<j) then quicksort(s,j);
   if (i<t) then quicksort(i,t);
end;

begin
assign(input,'milk.in');
assign(output,'milk.out');
reset(input);
rewrite(output);

readln(n,m);
for i:=1 to m do
   readln(o[i].v,o[i].a);
quicksort(1,m);
i:=0;
while d<n do begin
   inc(i);
   inc(d,o[i].a);
   inc(r,o[i].v*o[i].a);
end;
t:=d-n;
dec(r,o[i].v*t);
writeln(r);
close(output);
end.

1.3.2

Barn Repair (barn1)

其实也是贪心,还可以DP,我一开始是用搜索,但是搜索过不了第7个点,而且我看不出来到底是怎么回事,搜这个点时会出现类似死循环的症状。。。但是数据规模比它大得多的后两个点都能过。。。

很诡异

贪心是抄的代码,当时没精神自己写了,思路就是先把整个牛栏用一块木板盖住,每次将最长的间隔划开,直到没有间隔或者是板子数达到最大,这样盖住的间隔最小(所有更大的已经划出),这样板子的利用率最高,可以剩下的板子长度就是答案(最小长度)

dp过几天再写

code

1 dfs

{
ID: mfs.dev2
PROG: barn1
LANG: PASCAL
}

 

program barn1;

var
m,s,c,min,i:integer;
sn,fl:array[0..200] of integer;
t,tt:longint;
procedure quicksort(s,t:longint);
var
i,j,x,t1:integer;
begin
i:=s; j:=t; x:=sn[(i+j) div 2];
repeat
while (sn[i]<x) do inc(i);
while (sn[j]>x) do dec(j);
if (i<=j) then begin
     t1:=sn[i]; sn[i]:=sn[j]; sn[j]:=t1;
     inc(i); dec(j);
end;
until i>j;
if (s<j) then quicksort(s,j);
if (i<t) then quicksort(i,t);
end;

procedure dfs(l,n,i:integer);

begin
   if n>m then
    exit;
if l>min then
   exit;
if n+c-i<m then
   exit;
   if i>c then begin
    if l<min then
     min:=l;
    exit;
   end;
if i=3 then
t:=3;
{ inc(t);
tt:=i;
if t>12000000 then
   exit;}
   if fl[i]=0 then
   dfs(l+1,n+1,i+1);
   dfs(l+sn[i]-sn[i-1],n,i+1);
end;

begin
assign(input,'barn1.in');
assign(output,'barn1.out');
reset(input);rewrite(output);
readln(m,s,c);
for i:=1 to c do
   readln(sn[i]);
quicksort(1,c);
for i:=1 to c do
    if sn[i]=sn[i-1]+1 then
     fl[i]:=1;

min:=20000;
dfs(1,1,2);
writeln(min,' ',t,' ',tt);
{for i:=1 to c do
   writeln(sn[i],' ',fl[i]);}
close(output);
end.

2 贪心

{
ID: mfs.dev2
PROG: barn1
LANG: PASCAL
}
var
m,s,c,x,f,e,i,j,len,tot,em:byte;
occ:array[1..200]of boolean;
heap:array[1..200]of byte;

procedure add (len:byte);
var
i:byte;
begin
heap[em]:=len;
i:=em;
while (i<>1) and (heap[i div 2]<len) do
begin
    heap[i]:=heap[i div 2];
    heap[i div 2]:=len;
    i:=i div 2;
end;
while heap[em]<>0 do
    inc(em);
end;
//
procedure fix (s:byte);
var
i,j:byte;
begin
i:=s*2;
j:=s*2+1;
if (i>200) or (heap[i]=0) and (heap[j]=0) then
begin
    heap[s]:=0;
    if s<em then
      em:=s;
    exit;
end;
if heap[i]<heap[j] then
begin
    heap[s]:=heap[j];
    fix(j);
end
else
begin
    heap[s]:=heap[i];
    fix(i);
end;
end;
//
begin
assign(input,'barn1.in');
assign(output,'barn1.out');
reset(input);
rewrite(output);
readln(m,s,c);
for i:=1 to c do
begin
    readln(x);
    occ[x]:=true;
end;
f:=1;
while not occ[f] do
    inc(f);
e:=s;
while not occ[e] do
    dec(e);
em:=1;
i:=f+1;
while i<=e-1 do
    if not occ[i] then
    begin
      j:=i+1;
      while not occ[j] do
        inc(j);
      len:=j-i;
      add(len);
      i:=j+1;
    end
    else
      inc(i);
tot:=e-f+1;
i:=1;
while (heap[1]<>0) and (i<>m) do
begin
    dec(tot,heap[1]);
    fix(1);
    inc(i);
end;
writeln(tot);
close(input);
close(output);
end.

 

1.3.3

Calf Flac (calfflac)

这个使用的极为朴素的搜索

由于每个回文都有一个对称中心,一段里面每个字符(符合要求的)都可能是对称中心,于是枚举对称中心,向两边检测(忽略不和要求的字符),直到两边不相等(回文结束)或者有任何一边越界,得出最长回文,要分回文的字符数是奇数还是偶数两种情况,所以代码写得比较麻烦,有一段只是初始化不同,但是懒得用循环,于是用了复制粘贴。。。

nocow题解里有些很神的算法,但是没有具体讲解。。。有空去查查

顺便说,这个的测试数据里面有一个是个程序。。。真是什么都有,据某大牛说还有WS题的数据是一个情书(估计也是与字符串处理有关的,呵呵)

code

{
ID: mfs.dev2
PROG: calfflac
LANG: PASCAL
}


program calfflac;

var
s:array[0..20000] of char;
i,j,t,m,a,b,c,l,k1,k2,fl,lk,ma,mb,ff:longint;

function check(x:char):boolean;
var t:longint;
begin
check:=true;
t:=ord(x);
if t<65 then check:=false;
if (t>90) and (t<97) then check:=false;
if t>122 then check:=false;
end;

function jan(x,y:char):boolean;
var t1,t2:integer;
begin
jan:=false;
t1:=ord(x);t2:=ord(y);
if t1=t2 then jan:=true;
if (t1>=97) and (t1-32=t2) then jan:=true;
if (t1<=90) and (t1+32=t2) then jan:=true;
end;

begin
assign(input,'calfflac.in');
assign(output,'calfflac.out');
reset(input);rewrite(output);
l:=0;

while not eof do begin
   inc(l);
   read(s[l]);
end;

for i:=1 to l do begin
   if not check(s[i]) then continue;
k1:=0;k2:=0;t:=1;fl:=1;ff:=0;
while fl=1 do begin
inc(k1);inc(k2);
while not check(s[i+k1]) do begin
   if i+k1+1>l then begin ff:=1; fl:=0; break; end;
   inc(k1);
   end;
   while not check(s[i-k2]) do begin
   if i-k2<2 then begin ff:=1; fl:=0; break; end;
   inc(k2);
   end;
   if (jan(s[i+k1],s[i-k2])) and (ff=0) then begin
    inc(t,2);a:=i+k1;b:=i-k2;
   end else
    fl:=0;

   end;
   if t>m then begin
    m:=t;ma:=a;mb:=b;
   end;
   k1:=-1;k2:=0;t:=0;fl:=1;ff:=0;

   while fl=1 do begin
   inc(k1);inc(k2);
   while not check(s[i+k1]) do begin
   if i+k1+1>l then begin ff:=1;fl:=0; break; end;
   inc(k1);
   end;
   while not check(s[i-k2]) do begin
   if i-k2<2 then begin ff:=1; fl:=0; break; end;
   inc(k2);
   end;
   if (jan(s[i+k1],s[i-k2])) and (ff=0) then begin
    inc(t,2);a:=i+k1;b:=i-k2;
   end else
    fl:=0;
   end;
   if t>m then begin
    m:=t;ma:=a;mb:=b;
end;
end;
writeln(m);
for i:=mb to ma do
write(s[i]);
writeln;
close(output);
end.

 

1.3.4

Prime Cryptarithm (crypt1)

直接用枚举性质的搜索,时间复杂度O(n^5),但是n最大为9。。。

枚举两个乘数,分别乘出竖式中间的两个部分和最终结果,然后检测这三个东西是否超位数,是否每个数字都在给出的范围中(这个部分用了两次字符串/数,之间的转换实现,没想到更简洁的实现方法)

code

{
ID: mfs.dev2
PROG: crypt1
LANG: PASCAL
}


program crypt1;

var
f:array[0..10] of integer;
s:array[0..500] of integer;
n,a,b,c,d,e,i,j,o,p,k,t,nt,fl,ans:longint;


procedure check(x,y,z:longint);
var
   w:string;
   l,i,t:integer;
begin
   fl:=1;
   if (x>999) or (y>999) or (z>9999) then fl:=0;
   str(x,w);
   l:=length(w);
   for i:=1 to l do begin
    val(w[i],t);
    if f[t]=0 then fl:=0;
   end;
   str(y,w);
   l:=length(w);
   for i:=1 to l do begin
    val(w[i],t);
    if f[t]=0 then fl:=0;
   end;
str(z,w);
   l:=length(w);
   for i:=1 to l do begin
    val(w[i],t);
    if f[t]=0 then fl:=0;
   end;
end;

begin
assign(input,'crypt1.in');
assign(output,'crypt1.out');
reset(input);
rewrite(output);

readln(n);
for i:=1 to n do begin
   read(t);
   if f[t]=0 then begin
    inc(nt);
    s[nt]:=t;
   end;

   f[t]:=1;
end;
ans:=0;fl:=0;

for i:=1 to nt do
   for j:=1 to nt do
    for o:=1 to nt do
     for p:=1 to nt do
      for k:=1 to nt do begin
       a:=s[i]*100+s[j]*10+s[o];
       b:=s[p]*10+s[k];
       c:=a*s[p];
       d:=a*s[k];
       e:=a*b;
       check(c,d,e);
       if fl=1 then
        inc(ans);
      end;

   writeln(ans);
   close(output);
end.

posted @ 2008-12-11 12:24  jesonpeng  阅读(201)  评论(0)    收藏  举报