BZOJ2748:[HAOI2012]音量调节
Description
一个吉他手准备参加一场演出。他不喜欢在演出时始终使用同一个音量,所以他决定每一首歌之前他都要改变一次音量。在演出开始之前,他已经做好了一个列表,里面写着在每首歌开始之前他想要改变的音量是多少。每一次改变音量,他可以选择调高也可以调低。
音量用一个整数描述。输入文件中给定整数beginLevel,代表吉他刚开始的音量,以及整数maxLevel,代表吉他的最大音量。音量不能小于0也不能大于maxLevel。输入文件中还给定了n个整数c1,c2,c3…..cn,表示在第i首歌开始之前吉他手想要改变的音量是多少。
吉他手想以最大的音量演奏最后一首歌,你的任务是找到这个最大音量是多少。
Input
第一行依次为三个整数:n, beginLevel, maxlevel。
第二行依次为n个整数:c1,c2,c3…..cn。
Output
输出演奏最后一首歌的最大音量。如果吉他手无法避免音量低于0或者高于maxLevel,输出-1。
Sample Input
3 5 10
5 3 7
5 3 7
Sample Output
10
HINT
1<=N<=50,1<=Ci<=Maxlevel 1<=maxlevel<=1000
0<=beginlevel<=maxlevel
题解:
题目给出了许多个限制,问最大可行音量都是多少。
可以把每种音量是否可以取压缩为60个二进制状态,通过and运算来进行限制。
最后枚举最大答案。
代码:
1 const 2 ww=(1 shl 20)-1; 3 var 4 i,j,k,l,ll,n,nn,m,max:longint; 5 a,b:array[0..60]of qword; 6 begin 7 readln(n,l,m); nn:=m div 20; max:=(1 shl((m mod 20)+1))-1; 8 if(l<0)or(l>m)then begin writeln(-1); halt; end; 9 i:=l div 20; j:=l mod 20; 10 a[i]:=a[i]or(1 shl j); 11 for i:=1 to n do 12 begin 13 read(l); 14 for j:=0 to nn do b[j]:=0; 15 for j:=0 to nn do 16 begin 17 ll:=l; k:=j; 18 while(ll>20)and(k>=0)do 19 begin 20 ll:=ll-20; dec(k); 21 end; 22 if k>=0 then 23 begin 24 b[k]:=b[k]or(a[j] shr ll); 25 dec(k); ll:=20-ll; 26 if k>=0 then 27 b[k]:=(b[k]or(a[j] shl ll))and ww; 28 end; 29 ll:=l; k:=j; 30 while(ll>20)and(k<=nn)do 31 begin 32 ll:=ll-20; inc(k); 33 end; 34 if k<=nn then 35 begin 36 b[k]:=b[k]or(a[j] shl ll); 37 if k=nn then b[k]:=b[k]and max else b[k]:=b[k]and ww; 38 inc(k); ll:=20-ll; 39 if k<=nn then 40 begin 41 b[k]:=b[k]or(a[j] shr ll); 42 if k=nn then b[k]:=b[k]and max 43 else b[k]:=b[k]and ww; 44 end; 45 end; 46 end; 47 a:=b; 48 end; 49 for i:=nn downto 0 do 50 begin 51 if a[i]>0 then 52 begin 53 k:=0; 54 while a[i]>0 do 55 begin inc(k); a[i]:=a[i]shr 1; end; 56 k:=k-1; 57 writeln(i*20+k); halt; 58 end; 59 end; 60 writeln(-1); 61 end.