zoukankan      html  css  js  c++  java
  • NOIP2006代码及简析

    第一题,能量项链,比较经典的合并类动态规划,个人认为最简明的方程是f[i,j]=Max{f[i,j],f[i,k]+f[k+1,j]+a[i]*a[k+1]*a[j]},但这样写的话动归的循环没有办法实现,为了思维的简明,本人义无反顾的写下了记忆化搜索,效率没什么损失,都是0.01s出解,从这道题里也可以总结出一些什么,比如状态的分部规则性不明显时或者想出了动态方程但循环边界却十分纠结,记忆化搜索也是不错的选择,当然有些题目可以运用类似广度优先搜索的记忆化,属于正推,也有深搜的记忆化,其实它们本质上没有什么区别,都是状态的一些整合而已,动态规划题目并不难,看清实质就能行。

    View Code
     1 Program Energy(Input,Output);
    2 Var
    3 F : Array[0..301,0..301] Of Longint;
    4 A : Array[0..300] Of Longint;
    5 N,Ans : Longint;
    6 Procedure Init;
    7 Var
    8 I : Longint;
    9 Begin
    10 Readln(N);
    11 For I:=1 To N Do
    12 Begin
    13 Read(A[I]);
    14 A[I+N]:=A[I];
    15 End;
    16 End; { Init }
    17 Function Max(Aa,Bb :Longint ):Longint;
    18 Begin
    19 If Aa>Bb Then
    20 Exit(Aa);
    21 Exit(Bb);
    22 End; { Max }
    23 Function Dfs(I,J :Longint ):Longint;
    24 Var
    25 K : Longint;
    26 Begin
    27 If F[I,J]<>-1 Then
    28 Exit(F[I,J]);
    29 For K:=I To J-1 Do
    30 F[I,J]:=Max(F[I,J],Dfs(I,K)+Dfs(K+1,J)+A[I]*A[K+1]*A[J+1]);
    31 Exit(F[I,J]);
    32 End; { Dfs }
    33 Procedure Main;
    34 Var
    35 I,J : Longint;
    36 Begin
    37 For I:=1 To N+N Do
    38 For J:=1 To N+N Do
    39 F[I,J]:=-1;
    40 For I:=1 To N+N Do
    41 F[I,I]:=0;
    42 For I:=1 To N Do
    43 Ans:=Max(Ans,Dfs(I,I+N-1));
    44 End; { Main }
    45 Begin
    46 Assign(Input,'Energy.In');Reset(Input);
    47 Assign(Output,'Energy.Out');Rewrite(Output);
    48 Init;
    49 Main;
    50 Writeln(Ans);
    51 Close(Input);
    52 Close(Output);
    53 End.

    第二题,金明的预算方案,又是一道动态规划,可以用树形动归做,但是实现比较繁琐(如果是大牛请当我没说这句话),涉及泛化背包的一些知识(可以参考DD的背包九讲),如果是为了练习泛化背包,的确是个不错的题目,但考试的时候要把握全局,用最少的时间那最多的分数,题目中每个主件最多有两个附件,所以对于一组物品来说,只有以下几种方案:1.取主件,2.去主件和附件1,3.取主件和附件2,4.取主件附件1和附件2.所以只要在转移时把一组物品分四块转移,保留最大值即可,同样可以用滚动数组优化成一维。还有一个不错的优化,每个物品价值都是10的整数倍,所以可以把物品价值先都缩小10倍,最后答案*10输出即可。晒代码。

    View Code
     1 {这里l和r数组记录两个附件,IM为重要程度,v是体积,vv标记主件}
    2 Program Budget(Input,Output);
    3 Var
    4 F : Array[-35000..35000] Of Longint;
    5 V : Array[1..61] Of Longint;
    6 L,R : Array[1..61] Of Longint;
    7 Im : Array[1..61] Of Longint;
    8 Vv : Array[1..61] Of Boolean;
    9 Maxv,N : Longint;
    10 Procedure Init;
    11 Var
    12 I,J,X : Longint;
    13 Begin
    14 Fillchar(Vv,Sizeof(Vv),False);
    15 Readln(Maxv,N);
    16 For I:=1 To N Do
    17 Begin
    18 L[I]:=0;
    19 R[I]:=0;
    20 End;
    21 V[I]:=0;
    22 For I:=1 To N Do
    23 Begin
    24 Readln(V[I],Im[I],X);
    25 If X=0 Then
    26 Vv[I]:=True;
    27 If L[X]=0 Then
    28 L[X]:=I
    29 Else
    30 R[X]:=I;
    31 End;
    32 End; { Init }
    33 Function Max(Aa,Bb :Longint ):Longint;
    34 Begin
    35 If Aa>=Bb Then
    36 Exit(Aa);
    37 Exit(Bb);
    38 End; { Max }
    39 Procedure Main;
    40 Var
    41 I,J : Longint;
    42 Begin
    43 For I:=1 To N Do
    44 If Vv[I] Then
    45 For J:=Maxv Downto 1 Do
    46 Begin
    47 If J-V[I]>=0 Then
    48 F[J]:=Max(F[J],F[J-V[I]]+V[I]*Im[I]);
    49 If J-V[I]-V[L[I]]>=0 Then
    50 F[J]:=Max(F[J],F[J-V[I]-V[L[I]]]+Im[I]*V[I]+Im[L[I]]*V[L[I]]);
    51 If J-V[I]-V[R[I]]>=0 Then
    52 F[J]:=Max(F[J],F[J-V[I]-V[R[I]]]+Im[I]*V[I]+Im[R[I]]*V[R[I]]);
    53 If J-V[I]-V[L[I]]-V[R[I]]>=0 Then
    54 F[J]:=Max(F[J],F[J-V[I]-V[R[I]]-V[L[I]]]+Im[I]*V[I]+Im[L[I]]*V[L[I]]+Im[R[I]]*V[R[I]]);
    55 End;
    56 Writeln(F[Maxv]);
    57 End; { Main }
    58 Begin
    59 Assign(Input,'Budget.In');Reset(Input);
    60 Assign(Output,'Budget.Out');Rewrite(Output);
    61 Init;
    62 Main;
    63 Close(Input);
    64 Close(Output);
    65 End.

    第三题,终于不是动规题了,再一看,恶心的模拟题,不过再恶心也是模拟题,用数组记录各个工件当前完成的状态,记录时间,下一个步骤最早能开工的时间,当前机器的状态,顺便表示一下时间轴即可,注意读入时不要人工readln,第六个点有错误,数据告诉你每行8个,但有一行有九个数,而且最后一个数是下一行的第一个数,也就是说,从该行开始,数据错位了,所以用read啊!谈到这里,顺便说一下防止读入错误的常识,读入全是数字就直接read,不容易出问题,如果读入是一个字符矩阵,一定要小心,要人工readln,否则回车也会被当做一个字符读进去,然后你的字符矩阵就错了……

    View Code
     1 Program Jsp(Input,Output);
    2 Type Integer=Longint;
    3 Var
    4 P : Array[-10..20,-100..10000] Of Boolean;
    5 Top : Array[-100..2000] Of Integer;
    6 Start : Array[-100..2000] Of Integer;
    7 Longlong : Array[-100..2000] Of Longint;
    8 Time : Array[-100..500,-100..500] Of Integer;
    9 Need : Array[-100..500,-100..500] Of Integer;
    10 Now : Array[-100..500] Of Integer;
    11 M,N,Ans : Longint;
    12 Procedure Init;
    13 Var
    14 I,J : Longint;
    15 Begin
    16 Readln(M,N);
    17 For I:=1 To M*N Do
    18 Read(Start[I]);
    19 Readln;
    20 For I:=1 To N Do
    21 Begin
    22 For J:=1 To M Do
    23 Read(Need[I,J]);
    24 End;
    25 For I:=1 To N Do
    26 Begin
    27 For J:=1 To M Do
    28 Read(Time[I,J]);
    29 End;
    30 For I:=1 To N Do
    31 Longlong[I]:=1;
    32 Fillchar(Now,Sizeof(Now),0);
    33 Fillchar(P,Sizeof(P),False);
    34 End; { Init }
    35 Procedure Main;
    36 Var
    37 I,J,K,L : Longint;
    38 Mach,Long : Longint;
    39 Flag,Flag2 : Boolean;
    40 Begin
    41 For I:=1 To N*M Do
    42 Begin
    43 Inc(Now[Start[I]]);
    44 Long:=Time[Start[I],Now[Start[I]]];
    45 Mach:=Need[Start[I],Now[Start[I]]];
    46 Flag2:=False;
    47 For J:=1 To Top[Mach]+Longlong[Start[I]] Do
    48 Begin
    49 Flag2:=True;
    50 Flag:=True;
    51 For K:=J To J+Long-1 Do
    52 If (P[Mach,K])Or(J<Longlong[Start[I]]) Then
    53 Flag:=False;
    54 If Flag Then
    55 Break;
    56 End;
    57 If Not Flag2 Then
    58 J:=Longlong[Start[I]];
    59 For K:=J To J+Long-1 Do
    60 P[Mach,K]:=True;
    61 If J+Long-1>Top[Mach] Then
    62 Top[Mach]:=J+Long-1;
    63 If J+Long>Longlong[Start[I]] Then
    64 Longlong[Start[I]]:=J+Long;
    65 End;
    66 For I:=1 To M Do
    67 If Top[I]>Ans Then
    68 Ans:=Top[I];
    69 End; { Main }
    70 Procedure Print;
    71 Begin
    72 Writeln(Ans);
    73 End; { Print }
    74 Begin
    75 Assign(Input,'Jsp.In');Reset(Input);
    76 Assign(Output,'Jsp.Out');Rewrite(Output);
    77 Init;
    78 Main;
    79 Print;
    80 Close(Input);
    81 Close(Output);
    82 End.

    第四题,又来一道相当于动规的题目,实际上准确一点是递推,题目描述很清楚,但人读了之后一头雾水,耐下心来,原来是这样……  一定要明白题意,用

    f[i,j]表示2^k进制数长度为i且第一段为j(这里的第一段指的是二进制按k为基本段长从低位向高位数的最后一段),则进过两个数学计算

    f[i,j]=f[i,j+1]+f[i-1,j+1],由于当前长度状态仅和上一长度有关,可以用滚动数组优化,答案位数有很多,要用到高精度(这也是我认为题比较恶心的原因之一),不过昨天刚做了矩阵取数游戏,里面的高精度过程直接粘过来了,呵呵,偷个懒吧,注意计算f[i,j]要倒着计算。

    View Code
     1 Program Digital(Input,Output);
    2 Type
    3 Numbertype = Array[0..30] Of Int64;
    4 Var
    5 F : Array[0..1,0..600] Of Numbertype;
    6 Ans : Numbertype;
    7 N,M,Length : Longint;
    8 Function Plus(X,Y :Numbertype ):Numbertype;
    9 Var
    10 I,Len : Longint;
    11 Begin
    12 Fillchar(Plus,Sizeof(Plus),0);
    13 If X[0]>Y[0] Then
    14 Len:=X[0]
    15 Else
    16 Len:=Y[0];
    17 For I:=1 To Len Do
    18 Begin
    19 Plus[I]:=Plus[I]+X[I]+Y[I];
    20 Plus[I+1]:=Plus[I] Div 100000000;
    21 Plus[I]:=Plus[I] Mod 100000000;
    22 End;
    23 If Plus[Len+1]<>0 Then
    24 Plus[0]:=Len+1
    25 Else
    26 Plus[0]:=Len;
    27 End; { Plus }
    28 Procedure Print(X: Numbertype );
    29 Var
    30 I : Longint;
    31 Begin
    32 Write(X[X[0]]);
    33 For I:=X[0]-1 Downto 1 Do
    34 Begin
    35 Write((X[I] Div 10000000));
    36 Write((X[I] Div 1000000) Mod 10);
    37 Write((X[I] Div 100000) Mod 10);
    38 Write((X[I] Div 10000) Mod 10);
    39 Write((X[I] Div 1000) Mod 10);
    40 Write((X[I] Div 100) Mod 10);
    41 Write((X[I] Div 10) Mod 10);
    42 Write((X[I] Mod 10));
    43 End;
    44 End; { Print }
    45 Procedure Init;
    46 Var
    47 I : Longint;
    48 Begin
    49 Readln(M,N);
    50 Length:=N Div M;
    51 Ans[0]:=1; {对于Ans数组的初始化}
    52 Ans[1]:=0;
    53 For I:=1 To ((1<<M)-1) Do
    54 Begin
    55 F[0,I][0]:=1;
    56 F[0,I][1]:=1;
    57 End;
    58 End; { Init }
    59 Procedure Main;
    60 Var
    61 I,J : Longint;
    62 Position : Integer;
    63 Begin
    64 For I:=1 To Length-1 Do
    65 Begin
    66 Position:=I Mod 2;
    67 For J:=(1<<M)-1 Downto 1 Do
    68 Begin
    69 F[Position,J]:=Plus(F[1-Position,J+1],F[Position,J+1]);
    70 Ans:=Plus(Ans,F[Position,J]);
    71 End;
    72 End;
    73 If (N Mod M>0) Then {有多余的段}
    74 Begin
    75 Position:=Length Mod 2;
    76 For I:=(1<<M)-1 Downto 1 Do
    77 Begin
    78 F[Position,I]:=Plus(F[1-Position,I+1],F[Position,I+1]);
    79 If (1<<(N Mod M))-1>=I Then
    80 Ans:=Plus(Ans,F[Position,I]);
    81 End;
    82 End;
    83 End; { Main }
    84 Begin
    85 Assign(Input,'Digital.In');Reset(Input);
    86 Assign(Output,'Digital.Out');Rewrite(Output);
    87 Init;
    88 Main;
    89 Print(Ans);
    90 Close(Input);
    91 Close(Output);
    92 End.
  • 相关阅读:
    HDOJ 2871 Memory Control(线段树区间合并与查询)
    POJ 3468 A Simple Problem with Integers(线段树成段更新)
    POJ 2923 Relocation(状态压缩 + 两次DP)
    POJ 1436 Horizontally Visible Segments(线段树区间染色查询)
    POJ 2528 Mayor's posters(离散化的线段树)
    HDOJ 3308 LCIS(线段树区间合并与查询)
    异常处理的指导原则
    CSC命令
    .NET命名空间举例
    System.DateTime
  • 原文地址:https://www.cnblogs.com/neverforget/p/2215677.html
Copyright © 2011-2022 走看看