zoukankan      html  css  js  c++  java
  • [BZOJ1151][CTSC2007]动物园zoo 解题报告|DP|位运算

    Description

     

     

     

      最近一直在为了学习算法而做题,这道题是初一小神犇让我看的。感觉挺不错于是写了写。

      这道题如果是一条线的话我们可以构造一个DP f[i,j]表示以i为起点,i,i+1...i+4的取与不取的状态的二进制为j然后1~i积累的答案

      以前几乎没有这么写过,因为很难想到j是没有后效性的

      前一个状态有两种情况,i-1位取,i-1位不取

      也就是f[i-1,j >> 1] f[i-1,j >> 1+1 << 4]

      然后小朋友要怎么处理才能做到不重复不遗漏呢

      答案是记录以每个点为起点,连着5位的状态为j时从那个点出发的小朋友的开心个数

      显然当我们知道连着5位的状态时,完全可以推出该小朋友开不开心

      这一部分很容易脑补 但是真正写起来用位运算比较方便

      而i-1位是否取对当前也是没有影响的,所以这个DP就可以敲起来啦

      

      但是如何处理环形?

      固定前4位的取与不取的状态就可以啦...

      最后的时间复杂度就是DP状态的O(2^5*C)

      处理环的代价是O(2^4)

      最后是O(2^9*C) C<=5*10^5

      对于10s的时限来说还是可以过哒~

      1 /**************************************************************
      2     Problem: BZOJ1151
      3     Author: mjy0724
      4     Time:3760 ms
      5     Memory:30336 kb
      6 ****************************************************************/
      7 
      8 program bzoj1151;
      9 const maxn=100100;
     10 var i,j,x,n,c:longint;
     11     e,h,l,next,link:array[-1..maxn]of longint;
     12     hate,love:array[-1..maxn,-1..6]of boolean;
     13     num,f:array[-1..maxn,-1..32]of longint;
     14 
     15 function max(a,b:longint):longint;
     16 begin
     17     if a>b then exit(a) else exit(b);
     18 end;
     19 
     20 procedure solve_num;
     21 var i,j,k,t:longint;
     22 begin
     23     fillchar(num,sizeof(num),0);
     24     for i:=1 to n do
     25         for j:=0 to 31 do
     26         begin
     27             k:=link[i];
     28             while k<>0 do
     29             begin
     30                 for t:=1 to 5 do if (j and (1 << (5-t)))<>0 then
     31                 //这个位运算刚开始一直出错,不能写成=1因为and之后虽然只有1位是1但是不一定在最后一位QAQ
     32                 begin
     33                     if love[k,t] then
     34                     begin
     35                         inc(num[i,j]);break;//这里的break很重要 因为1个小朋友只能算一次
     36                     end;
     37                 end else
     38                 begin
     39                     if hate[k,t] then
     40                     begin
     41                         inc(num[i,j]);break;
     42                     end;
     43                 end;
     44                 k:=next[k];
     45             end;
     46         end;
     47 end;
     48 
     49 procedure dp;
     50 var head,i,j,tot,k,ans:longint;
     51 begin
     52     ans:=0;
     53     for head:=0 to 15 do//枚举前4位的状态
     54     begin
     55         fillchar(f,sizeof(f),192);
     56         fillchar(f[0],sizeof(f[0]),0);
     57         for i:=1 to 4 do
     58             for j:=(head << i) and 31 to (head << i) and 31+1 << i-1 do //and 31是小小的位运算技巧,把前面的头都去掉啦
     59                 f[i,j]:=max(f[i-1,j >> 1],f[i-1,j >> 1+1 << 4])+num[i,j];
     60 
     61         for i:=5 to n-4 do
     62             for j:=0 to 31 do
     63                 f[i,j]:=max(f[i-1,j >> 1],f[i-1,j >> 1+1 << 4])+num[i,j];
     64         tot:=0;
     65         for i:=n-3 to n do
     66         begin
     67             inc(tot);
     68             for k:=0 to 1 << (5-tot)-1 do
     69             begin
     70                 j:=k << tot+head >> (n-i);
     71                 f[i,j]:=max(f[i-1,j >> 1],f[i-1,j >> 1+1 << 4])+num[i,j];
     72             end;
     73         end;
     74 
     75         for i:=0 to 31 do ans:=max(ans,f[n,i]);
     76     end;
     77     writeln(ans);
     78 end;
     79 
     80 begin
     81     readln(n,c);
     82     fillchar(hate,sizeof(hate),false);
     83     fillchar(love,sizeof(love),false);
     84         for i:=1 to c do
     85     begin
     86         read(e[i],h[i],l[i]);
     87         for j:=1 to h[i] do
     88         begin
     89             read(x);
     90                 if x>=e[i] then hate[i,x-e[i]+1]:=true else hate[i,(x+n-e[i]) mod n+1]:=true;//这里处理环的情况 表示第i个小朋友视野里的第几个是否讨厌
     91         end;
     92         for j:=1 to l[i] do
     93         begin
     94             read(x);
     95                 if x>=e[i] then love[i,x-e[i]+1]:=true else love[i,(x+n-e[i]) mod n+1]:=true;
     96         end;
     97         readln;
     98             next[i]:=link[e[i]];link[e[i]]:=i;
     99     end;
    100        solve_num;
    101        dp;
    102 end.
  • 相关阅读:
    Wauzh原理简析及audit规则风险评估
    浅析这句经常在框架中出现的JS代码加深对bind的理解
    浅析如何做web安全问题
    浅析JavaScript到底是什么
    浅析webpack异步加载原理及分包策略
    浅析JavaScript的执行机制
    浅析如何提高代码可读性复用性拓展性
    浅析代码编译过程
    浅析JavaScript的7种异常类型及如何快速排查
    浅析浏览器是如何调度进程和线程的
  • 原文地址:https://www.cnblogs.com/mjy0724/p/4421333.html
Copyright © 2011-2022 走看看