USACO Section 1.5 题解

          以后编程的时间越来越少罗,上高中要努力罗。这个只能当业余活动,没办法谁叫我没能力上省队啊,有能力的话我都不管文化科了。加油吧,考上个好大学,以后就可以好好研究、编程罗。不过比赛还是要去打打酱油的,看看自己有没进步,少许进步我便满意了。noip复赛貌似在11月把,还有3个月,有时间就练练吧。

 

 

----------------------------------------------------------美丽的分界线------------------------------------------------------------------

 

 

USACO 1.5.1 Number Triangles 数字金字塔 

 

学DP的入门题

 

 

program  numtri(input,output);
var
  n,i,j:longint;
  f:array[1..1000,1..1000] of longint;
procedure init;
 begin
   assign(input,'numtri.in');
   assign(output,'numtri.out');
   reset(input);
   rewrite(output);
 end;
procedure outit;
 begin
   close(input);
   close(output);
 end;
function max(x,y:longint):longint;
 begin
   if x>y then max:=x
          else max:=y;
 end;
begin
  init;
  readln(n);
  for i:=1 to n do
    begin
      for j:=1 to i do read(f[i,j]);
      readln;
    end;
  for i:=n-1 downto 1 do
    for j:=1 to i do
      f[i,j]:=max(f[i,j]+f[i+1,j],f[i,j]+f[i+1,j+1]);
  writeln(f[1,1]);
  outit;
end.


 

 

USACO 1.5.2 Prime Palindromes 回文质数

 

这题主要是解决超时问题。做法:先制造回文数,在判断素数。而且回文数除11外,偶数位的回文数都不是素数,都可被11整除。(提示里面有)

USACO里面好多解法,都很简单,我没仔细看。

 

 

program pprime(input,output);
 var
   a,b,i,j,k,med,total,n:longint;
   s,s1:string;
   g:boolean;
   f:array[1..10000] of boolean;   
   prime:array[1..5000] of longint;
procedure init;
 begin
   assign(input,'pprime.in');
   assign(output,'pprime.out');
   reset(input);
   rewrite(output);
 end;
procedure outit;
 begin
   close(input);
   close(output);
 end;
procedure sushu;   //10000内素数表
 var
   i,j:longint;
 begin
   f[1]:=false;
   i:=2;
   while i<=100 do
     begin
       if f[i] then
         begin
           j:=i*2;
           while j<=10000 do begin f[j]:=false;inc(j,i);end;
         end;
       inc(i);
     end;
   total:=0;
   for i:=2 to 10000 do
     if f[i] then begin inc(total);prime[total]:=i;end;
 end;
function ok(k:longint):boolean;   //判断是否是素数
 var
   i:longint;
 begin
   for i:=1 to total do
     if prime[i]>trunc(sqrt(k)) then break
                else if k mod prime[i]=0 then exit(false);
   exit(true);
 end;
begin
  init;
  fillchar(f,sizeof(f),true);
  sushu;
  readln(a,b);
  i:=1;n:=10;
  for med:=1 to 7 do     //回文素数的位数,因为8是偶数,9就超过...
    begin
      if med=2 then 
        begin
          if (a<=11)and(b>=11)then writeln(11);
          continue;
        end;
      if odd(med) then
        begin
          while i<n do
            begin
              str(i,s1);
              s:=s1;
              for j:=length(s1)-1 downto 1 do s:=s+s1[j];    //构成回文
              val(s,k);
              if a<=k then
                begin
                  if k>b then begin outit;halt;end;
                  if ok(k) then writeln(k);
                end;
              inc(i);
            end;
          n:=n*10;   //n是控制i累加,例如1位素数n=10,3位素数n=100,5位素数n=1000
        end;
    end;
  outit;
end.


 

 

USACO 1.5.3 Superprime Rib 特殊的质数肋骨

 

简单的dfs,第一位只能是[2,3,5,7],而后面的位数全都只能是[1,3,7,9],因为是其他的必定是合数。

 

program sprime(input,output);
 var
   n:longint;
procedure init;
 begin
   assign(input,'sprime.in');
   assign(output,'sprime.out');
   reset(input);
   rewrite(output);
 end;
procedure outit;
 begin
   close(input);
   close(output);
 end;
function ok(k:longint):boolean;
 var
   i:longint;
 begin
   for i:=2 to trunc(sqrt(k)) do
     if k mod i=0 then exit(false);
   exit(true);
 end;
procedure dfs(x,y:longint);
 begin
   if y=0 then begin writeln(x);exit;end;
   if ok(x*10+1) then dfs(x*10+1,y-1);
   if ok(x*10+3) then dfs(x*10+3,y-1);
   if ok(x*10+7) then dfs(x*10+7,y-1);
   if ok(x*10+9) then dfs(x*10+9,y-1);
 end;
begin
  init;
  readln(n);
  dfs(2,n-1);
  dfs(3,n-1);
  dfs(5,n-1);
  dfs(7,n-1);
  outit;
end.


 

 

USACO 1.5.4 Checker Challenge 跳棋的挑战

 

典型的n皇后问题,但13皇后会超时,所以要优化。优化方法有很多种,USACO题解都有,我用的是对称,减少一半时间。

如果是n为偶数,第一行的皇后在1~n div 2搜索,结果*2就行。但奇数,如果最后个皇后在中间列,则有4种方案,所以要记录最后个皇后是否在中间列,是的话这种方案还要*2。

 

 

program checker(input,output);
var
  n,i,j,ans,num:longint;
  line:array[1..13] of longint;
  row,hy1,hy2:array[-30..30] of boolean;
procedure init;
 begin
   assign(input,'checker.in');
   assign(output,'checker.out');
   reset(input);
   rewrite(output);
 end;
procedure outit;
 begin
   close(input);
   close(output);
 end;
procedure print;
 var
   i:longint;
 begin
   for i:=1 to n-1 do write(line[i],' ');
   writeln(line[n]);
 end;
procedure dfs(k:longint);
 var
   i:longint;
 begin
   if k=n+1 then
     begin
       inc(ans);
       if ans<=3 then print;
       if line[n]=n div 2+1 then inc(num);    //判断最后个皇后是否在中间列
     end
            else
       for i:=1 to n do
         if row[i] and hy1[k-i] and hy2[k+i] then
           begin
             line[k]:=i;
             row[i]:=false;
             hy1[k-i]:=false;
             hy2[k+i]:=false;
             dfs(k+1);
             row[i]:=true;
             hy1[k-i]:=true;
             hy2[k+i]:=true;
           end;
 end;
begin
  init;
  fillchar(row,sizeof(row),true);
  fillchar(hy1,sizeof(hy1),true);
  fillchar(hy2,sizeof(hy2),true);
  readln(n);
  if n=6 then dfs(1)               //n=6是不能对称
         else
           begin
             for i:=1 to n div 2 do
               if row[i] and hy1[1-i] and hy2[1+i] then
                 begin
                   line[1]:=i;
                   row[i]:=false;
                   hy1[1-i]:=false;
                   hy2[1+i]:=false;
                   dfs(2);
                   row[i]:=true;
                   hy1[1-i]:=true;
                   hy2[1+i]:=true;
                 end;
             ans:=ans*2;num:=num*2;
             if odd(n) then inc(ans,num);
           end;
  writeln(ans);
  outit;
end.


 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值