2017.8.09 SSL 模拟赛

T1:
17倍 Times17:
题目大意:
给出一个二进制数N,求出17*N的二进制数的值。

数据范围:
N的位数不超过1000位。

题解:
枚举:
不难发现,对于二进制上的第i位,代表的是2^i次方,而他的十七倍则是他的第i+4位+1且他本身这一位为1,然后直接枚举这个数的位数,如果这一位存在1,则给他的i+4的位+1,因为他本身已经有一个了,所以1倍+16倍就可以了。

时间复杂度:O(N的长度)

var
 st:ansistring;
 i,long,m:longint;
 a,b:array [-1..1005] of longint;
begin
 readln(st);
  long:=length(st);
   for i:=1005-long+1 to 1005 do a[i]:=ord(st[long-(1005-i)])-48;
    for i:=1005 downto 1005-long+1 do if a[i]=1 then b[i-4]:=b[i-4]+1;
    for i:=1005 downto 1005-long-6 do a[i]:=a[i]+b[i];
    for i:=1005 downto 1006-long-6 do
     if a[i] div 2>=1 then
      begin
        a[i-1]:=a[i-1]+a[i] div 2;
        a[i]:=a[i] mod 2;
      end;
  m:=1;
   while (a[m]=0) and (m<=1005) do inc(m);
  for i:=m to 1005 do write(a[i]);
end.

T2:
马蹄印 Horseshoes:
题目大意:
对于一个完美的平衡序列,是先一定数量的左括号然后是与左括号相同数量的右括号。例如:(((())))。
农场是一个N*N的方格,每个小方格中都有一个马蹄印。从方格的最左上角的地方开始出发,然后每次可以向上或者向下或者向左或者向右移动一步,不能重复经过任何小方格,使得他走过的每个小方格中的马蹄印能够组成一个完美的平衡序列,求这个序列的长度。
数据范围:2<=N<=5

题解:
dfs:
这题的数据好尴尬,裸裸的搜索就可以了,
然后注意一下几个要求:
①每个点只能走一遍
②能向上下左右走
然后要优美的同学,还有一个优化,就是如果当前搜的序列已经出现了’)’则它之后搜到了’(‘就直接exit。

const
    dx:array [1..4] of integer=(1,0,0,-1);
    dy:array [1..4] of integer=(0,1,-1,0);

var
    a:array [0..6,0..6] of char;
    b:array [0..6,0..6] of boolean;
    i,j,n,max:longint;

function check(aa,bb:longint):boolean;
begin
    if (b[aa,bb]) or (aa<1) or (aa>n) or (bb<1) or (bb>n) then exit(false);
    exit(true)
end;

procedure dfs(x,y,left,right:longint;pd:boolean);
var
    i,p,q:longint;
    pdd:boolean;
begin
    b[x,y]:=true;
    p:=0; q:=0;
    pdd:=false;
    if a[x,y]='('
       then begin if not(pd) then p:=1 end
       else begin pdd:=true; q:=1; end;
    if (p=1) or (q=1)
       then begin
                if left+p=right+q then
                   if left+p>max then max:=left+p;
                for i:=1 to 4 do
                  if check(x+dx[i],y+dy[i])
                     then dfs(x+dx[i],y+dy[i],left+p,right+q,pdd);
            end;
    b[x,y]:=false;
end;

begin
    readln(n);
    for i:=1 to n do
    begin
         for j:=1 to n do read(a[i,j]);
         readln;
    end;
    dfs(1,1,0,0,false);
    writeln(2*max);
end.

T3:
排队的奶牛 Cows in a Row:
题目大意:
农夫约翰的N只奶牛排成了一条直线,从左到右第i只奶牛的编号是Bi。约翰认为他的奶牛队列中存在某段连续区间都是相同序号的,那他的队列就非常的美观。为了创造这样的一个连续区间,约翰决定将某个特定的序号的奶牛全部剔除队列,然后求这样以后,能出现的最长的区间长度。

数据范围:
1<=N<=1000,奶牛序号的范围是0到1000000。

题解:
因为只有N头牛,而序号只有1000000最大,所以我们开个桶去塞,将出现的序号塞出来。
因为序号不多于1000个,就直接枚举每种奶牛被剔除的情况。
最后在出现过的序号中找答案。
时间复杂度:O(N^2)

var
    a:Array [0..1000001] of boolean;
    ans:array [0..1000001] of longint;
    p,c:Array [0..1001] of longint;
    i,j,n,max:longint;

procedure find(x:longint);
var
    i,j,k:longint;
begin
    i:=1;
    while i<=n do
    begin
         while (c[i]=x) and (ido inc(i);
         j:=0;
         k:=1;
         while ((c[i+j+1]=x) or (c[i]=c[i+j+1])) and (i+j+1<=n) do
         begin
              inc(j);
              if c[i+j]=c[i] then inc(k);
         end;
         if k>ans[c[i]]
            then ans[c[i]]:=k;
         i:=i+j+1;
    end;
end;

begin
    readln(n);
    for i:=1 to n do
    begin
         readln(c[i]);
         if not(a[c[i]])
            then begin
                     inc(p[0]);
                     p[p[0]]:=c[i];
                 end;
         a[c[i]]:=true;
    end;
    for i:=1 to p[0] do find(p[i]);

    for i:=1 to p[0] do
      if ans[p[i]]>max then max:=ans[p[i]];
    writeln(max);
end.

T4:
景观美化 Landscaping:
题目大意:
花园由N块花圃组成,第i块花圃初始的时候有Ai数量的泥土。为了达到美化的目的,必须使得第i块花圃的泥土数量Ai变成Bi。
约翰有三个选择:
①买一个单位的泥土放进任意花圃中,代价是X;
②将一个单位的泥土从某一个花圃中除去,代价是Y;
③将第i块花圃中的一个单位的泥土搬运到第j块花圃中,大家是Z*|i-j|。

数据范围:
1<=N<=100,
0<=Ai,Bi<=10,
0<=X,Y,Z<=1000。

题解:
这题有2种做法:
①这题我们将每个花圃的泥土都分开来,例如,我们将3,1,4,1的泥土数量分成1,1,1,2,3,3,3,3,4。三个1表示第一个花圃中有3个单位的泥土,以此类推。
然后目标状态跟当前状态都这样做
接着我们设f[i,j]表示用了前i个当前状态转化到前j个目标状态所需要的最小代价。
然后DP:
初值:
i=0 则 j个全部直接购买:f[i,j]=j*x
j=0 则 i个全部直接除去:f[i,j]=i*y
f[i,j]=min(f[i-1,j]+y,f[i,j-1]+x,f[i-1,j-1]+z*abs(a[i]-b[j]))
f[i-1,j]+y
i-1个转化到j个的最小值+直接除去第i个
f[i,j-1]+x
i个转化到j-1个的最小值+直接买掉第j个
f[i-1,j-1]+z*abs(a[i]-b[j])
i-1个转化到j-1个的最小值+用第i个转化到第j个

时间复杂度:O(a[i]总和 * b[i]总和)

var
   f:array [0..1001,0..1001] of longint;
   a,b:array [0..1001] of longint;
   i,j,n,x,y,z,a1,b1:longint;

function min(aa,bb:longint):longint;
begin
    if aa>bb then exit(bb);
    exit(aa); 
end;

begin
   readln(n,x,y,z);
   for i:=1 to n do
   begin
        readln(a1,b1);
        for j:=1 to a1 do
        begin
             inc(a[0]);
             a[a[0]]:=i;
        end;
        for j:=1 to b1 do
        begin
             inc(b[0]);
             b[b[0]]:=i;
        end;
   end;
   for i:=0 to a[0] do
     for j:=0 to b[0] do
     begin
              if i=0 then f[i,j]:=j*x
         else if j=0 then f[i,j]:=i*y
         else f[i,j]:=min(f[i-1,j-1]+z*abs(a[i]-b[j]),min(f[i,j-1]+x,f[i-1,j]+y));
     end;
   writeln(f[a[0],b[0]]);
end.

你可能感兴趣的:(暴力/枚举/模拟,深搜dfs,动态规划)