zoukankan      html  css  js  c++  java
  • bzoj1306

    非常好的一道搜索题
    首先没有别的好办法就只能搜,基于对称性我只要搜对角线上半部分即可
    然后有些惯用的剪枝啦什么的,具体见程序
    然后代码很短,然后TLE了(但好像也有人过了)
    然后就不知道怎么优化了,看到CLJ大神的空间发现这道题是可以记忆化搜索的orz
    首先当搜索完某个队伍的胜负情况后,观察剩下的队伍已确定的得分和最终得分之差,我们称作剩余状态
    显然,我们对后面队伍胜负的搜索得到的方案数与之前的搜索状态无关
    并且,像剩下三支队伍剩余状态是1 0 3和 0 3 1是等价的,方案数相同(即顺序并不影响)
    也就是说如果两次搜索的剩余状态一样,我们直接加即可,不用再搜一次
    因此我们想到了记忆化搜索,对于状态的判断自然而然想到用hash

      1 const ch:array[1..3] of longint=(3,1,0);
      2       key=200007;
      3 
      4 type link=^node;
      5      node=record
      6        num,loc:longint;
      7        next:link;
      8      end;
      9 
     10 var s,c,b:array[0..10] of longint;
     11     a:array[0..1000007,0..10] of longint;
     12     w:array[0..key] of link;
     13     ans,u,i,n,tot:longint;
     14 
     15 procedure swap(var a,b:longint);
     16   var c:longint;
     17   begin
     18     c:=a;
     19     a:=b;
     20     b:=c;
     21   end;
     22 
     23 function work(m:longint):longint;   //排序,计算hash值
     24   var i,j,p:longint;
     25   begin
     26     work:=0;
     27     for i:=1 to m-1 do
     28     begin
     29       p:=i;
     30       for j:=i+1 to m do
     31         if b[j]>b[p] then p:=j;
     32       swap(b[i],b[p]);
     33     end;
     34     for i:=1 to m do
     35       work:=(work+sqr(b[i])*sqr(i)) mod key;
     36   end;
     37 
     38 function calc(l,r:longint):longint;
     39   var k,h:longint;
     40   begin
     41     h:=0;
     42     for k:=1 to n do
     43       b[k]:=100;
     44     for k:=l to r do
     45     begin
     46       inc(h);
     47       b[h]:=c[k]-s[k];
     48     end;
     49     calc:=work(h);
     50   end;
     51 
     52 procedure add(x,y:longint);
     53   var p:link;
     54       i:longint;
     55   begin
     56     new(p);
     57     inc(tot);
     58     for i:=1 to n do
     59       a[tot,i]:=b[i];
     60     p^.loc:=tot;
     61     p^.num:=y;
     62     p^.next:=w[x];
     63     w[x]:=p;
     64   end;
     65 
     66 function find(x,y:longint):longint;
     67   var p:link;
     68       f:boolean;
     69       i:longint;
     70 
     71   begin
     72     p:=w[x];
     73     while p<>nil do
     74     begin
     75       f:=true;
     76       u:=p^.loc;
     77       for i:=1 to n do
     78         if (a[u,i]<>b[i]) then
     79         begin
     80           f:=false;
     81           break;
     82         end;
     83       if f then exit(p^.num);
     84       p:=p^.next;
     85     end;
     86     if y<>-1 then add(x,y);   //没有重复的状态则插入
     87     exit(-1);
     88   end;
     89 
     90 function dfs(t,j:longint):longint;
     91   var k,h,q:longint;
     92   begin
     93     if t=n then
     94     begin
     95       if s[n]=c[n] then exit(1);
     96       exit(0);
     97     end;
     98     if s[t]>c[t] then exit(0);   //剪枝,显然确定的得分不能大于最终得分的
     99     if s[t]+(n+1-j)*3<c[t] then exit(0);  //剪枝,如果后面全胜也不能达到最终得分剪掉
    100     if j=t+1 then  
    101     begin
    102       h:=calc(t,n);
    103       q:=find(h,-1);   //-1表示只是单纯的查询
    104       if q<>-1 then exit(q);  //记忆化
    105     end;
    106     q:=0;
    107     if j<=n then
    108     begin
    109       for k:=1 to 3 do
    110       begin
    111         s[t]:=s[t]+ch[k];
    112         s[j]:=s[j]+ch[4-k];
    113         if not((s[j]>c[j]) or (s[j]+(n+1-t)*3<c[j])) then q:=q+dfs(t,j+1);
    114         s[t]:=s[t]-ch[k];
    115         s[j]:=s[j]-ch[4-k];
    116       end;
    117     end
    118     else if s[t]=c[t] then  //搜完一支队伍我们就判重/记录剩余状态
    119     begin
    120       q:=dfs(t+1,t+2);
    121       h:=calc(t+1,n);
    122       k:=find(h,q);
    123     end;
    124     exit(q);
    125   end;
    126 
    127 begin
    128   readln(n);
    129   for i:=1 to n do
    130     read(c[i]);
    131   writeln(dfs(1,2));
    132 end.
    View Code
  • 相关阅读:
    51nod 1416 两点 dfs
    Codeforces Round #424 (Div. 2) A-C
    Codeforces Round #423 (Div. 2) A-C
    Codeforces Round #422 (Div. 2) A-C
    HDU 6077 Time To Get Up 模拟
    51nod 1381 硬币游戏 概率
    51nod 1100 斜率最大 计算几何
    hihocoder 1287 : 数论一·Miller-Rabin质数测试 大质数判定
    字典树
    数论
  • 原文地址:https://www.cnblogs.com/phile/p/4473113.html
Copyright © 2011-2022 走看看