p2206.dpr

来自「高手写的所有acm例程 在acm.zju.edu.cn 上的题目的例程」· DPR 代码 · 共 137 行

DPR
137
字号
{
        算法 : 搜索 + 剪枝优化
        
}
program p2206;

{$APPTYPE CONSOLE}

const
        maxsize         = 1000;
        maxask          = 10;
        maxdie          = 6;

type    
        Topt    = array[0..1 , 0..maxsize] of int64;
        Tbase   = array[1..maxask] of int64;
        Tdown   = array[1..50 , 1..maxask] of int64;
        TLimit  = array[1..maxask] of int64;
        Tcho    = array[1..maxdie] of int64;

var
        n       : Longint;
        r       : Longint;
        find    : Boolean;
        max     : Longint;
        opt     : Topt;
        v , c   : Tbase;
        down    : Tdown;
        Limit   : TLimit;
        cho     : Tcho;
        Leave   : Tbase;

procedure init;
var     i , j   : Longint;
        k , m   : Longint;
        a , b   : Longint;
        t , l   : Longint;
begin
fillchar ( opt , sizeof ( opt ) , 0 ); a := 0; b := 1;
opt [a] [0] := 1; max := 0;
for i := 1 to n do
        begin
        for j := 0 to max do opt [b] [j] := 0;
        read ( l ); m := 0;
        for j := 1 to l do
                begin
                read ( t ); if t > m then m := t;
                for k := t to max + t do
                        if opt [b] [k] < $7fffffffffffffff - opt [a] [k - t] then inc ( opt [b] [k] , opt [a] [k - t] );
                end;
        readln;
        inc ( max , m );
        a := 1 - a;
        b := 1 - b;
        end;

read ( r , n );
for i := 1 to n do read ( v [i] , c [i] ); readln;
fillchar ( Limit , sizeof ( Limit ) , 0 );

for i := 1 to 50 do
        for j := 1 to n do
                begin
                if ( v [j] >= i ) then down [i] [j] := opt [a] [v [j] - i]
                        else down [i] [j] := 0;
                if down [i] [j] > Limit [j] then Limit [j] := down [i] [j];
                end;
end;

procedure search ( dep , start : Longint );
var     i , j   : Longint;
        zero    : Boolean;
        flag    : Boolean;
begin
zero := true;
for i := 1 to n do
        begin
        if ( Limit [i] * ( r - dep + 1 ) < Leave [i] ) then exit;
        if Leave [i] <> 0 then zero := false;
        end;

if ( dep = r + 1 ) and ( zero ) then
        begin
        find := true;
        exit;
        end;

for i := start to 50 do
        begin
        cho [dep] := i; flag := true;
        for j := 1 to n do
                begin
                dec ( Leave [j] , down [i] [j] );
                if ( Leave [j] < 0 ) then flag := false;
                end;
        if flag then search ( dep + 1 , i );
        
        if find then exit;
        
        for j := 1 to n do
                inc ( Leave [j] , down [i] [j] );
        end;
end;

procedure main;
var     i       : Longint;
begin

// 剪枝 1 :采用每种最大的策略仍不能满足要求
for i := 1 to n do if ( v [i] > max + 50 ) then
        begin
        writeln ( 'Impossible' );
        exit;
        end;

find := false;
Leave := c;
search ( 1 , 1 );
if not find then writeln ( 'Impossible' )
        else begin
        write ( 'Final die face values are' );
        for i := 1 to r do write ( ' ' , cho [i] );
        writeln;
        end;
        
end;

begin
readln ( n );
while ( n <> 0 ) do
        begin
        init;
        main;
        readln ( n );
        end;
end.

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?