| ||||||||||
| Online Judge | Problem Set | Authors | Online Contests | User | ||||||
|---|---|---|---|---|---|---|---|---|---|---|
| Web Board Home Page F.A.Qs Statistical Charts | Current Contest Past Contests Scheduled Contests Award Contest | |||||||||
不会构造,于是直接状压DP打表。附代码及解题报告。状态的表示:状态只与前两行的宝石有关。最朴素的表示就4^(2n)次方的了,暴力转移的话,n=7转移一行
大约需要4^14*4^7次,严重不可接受。
但我们发现,很多状态表示是无用的。例如当前行某一列是diamond,但diamond根本不关心前一行这一
列的值,为何需要用4个状态表示它?于是优化每一格状态表示到10种:(a-b表示某列当前行是a,上一
行是b)
0=ruby-emerald 1=ruby-sapphire 2=ruby-diamond 3=ruby-other
4=emerald-sapphire 5=emerald-diamond 6=emerald-other
7=sapphire-diamond 8=sapphire-other
9=diamond-other
这样状态最多只有10^7种了。这样代码跑个一两天也是可以跑完的。但我们还可以优化。
我们发现很多状态根本不能用,例如如果有这种情况
?R?
RRE
这个状态中,下一行第二列无论怎么填都不能满足ruby的要求,完全可以舍弃。这个过程可以在10^7*7
时间内完成。我们发现这时n=7时状态只有不到200万种了(还是20万?记不清了)。
然后,转移也可以优化。例如这个状态
?R?
SRE
这个状态中,第二列只能填diamond。于是可以先把那些列可以填那些处理出来,可以极大地加快运行速
度。我试验了一下,这时n=7时每一行只要转移不到6亿次。这样代码就可以在一个小时左右把表打完了。
打表用代码:
var
a,b,cc:array[0..11] of longint;
s:array[0..11] of set of byte;
dt:array[0..11,0..11] of longint;
d:array[0..10000000] of longint;
ok:array[0..10000000] of longint;
dp:array[1..7,0..2000000] of longint;
function checkinit(n,x1:longint):boolean;
var i:longint;
begin for i:=1 to n do
begin a[i]:=x1 mod 10;
x1:=x1 div 10;
if not (a[i] in [3,6,8,9]) then exit(false);
end;
exit(true);
end;
function checkvl(n,x1:longint):longint;
var i,res:longint;
begin res:=0;
for i:=1 to n do
begin a[i]:=x1 mod 10;
x1:=x1 div 10;
if a[i] in [0,1,2,3] then inc(res);
end;
exit(res);
end;
function check(n,x1:longint):boolean;
var i,x,y:longint;
begin for i:=1 to n do
begin a[i]:=x1 mod 10;
x1:=x1 div 10;
end;
case a[1] of
0: if a[2] in [0,1,2,3,4,5,6] then exit(false);
1: if a[2] in [0,1,2,3,7,8] then exit(false);
2: if a[2] in [0,1,2,3,9] then exit(false);
3: exit(false);
6: if a[2] in [0,1,2,3,4,5,6] then exit(false);
end;
case a[n] of
0: if a[n-1] in [0,1,2,3,4,5,6] then exit(false);
1: if a[n-1] in [0,1,2,3,7,8] then exit(false);
2: if a[n-1] in [0,1,2,3,9] then exit(false);
3: exit(false);
6: if a[n-1] in [0,1,2,3,4,5,6] then exit(false);
end;
for i:=2 to n-1 do
case a[i] of
0: begin
if a[i-1] in [7,8,9] then continue;
if a[i+1] in [7,8,9] then continue;
exit(false);
end;
1: begin
if a[i-1] in [4,5,6,9] then continue;
if a[i+1] in [4,5,6,9] then continue;
exit(false);
end;
2: begin
if a[i-1] in [4,5,6,7,8] then continue;
if a[i+1] in [4,5,6,7,8] then continue;
exit(false);
end;
3: begin
if a[i-1] in [0,1,2,3] then exit(false);
if a[i+1] in [0,1,2,3] then exit(false);
if a[i-1] in [4,5,6] then x:=2;
if a[i-1] in [7,8] then x:=3;
if a[i-1]=9 then x:=4;
if a[i+1] in [4,5,6] then y:=2;
if a[i+1] in [7,8] then y:=3;
if a[i+1]=9 then y:=4;
if x=y then exit(false);
end;
6: begin
if a[i-1] in [7,8,9] then continue;
if a[i+1] in [7,8,9] then continue;
exit(false);
end;
end;
exit(true);
end;
procedure expand(n,x1,next:longint);
var i,x,y,j,cur,xw:longint;
begin xw:=x1;
for i:=1 to n do
begin a[i]:=x1 mod 10;
x1:=x1 div 10;
end;
case a[1] of
0: if a[2] in [7,8] then s[1]:=[9] else s[1]:=[8];
1: if a[2] in [4,5,6] then s[1]:=[9] else s[1]:=[6];
2: if a[2] in [4,5,6] then s[1]:=[8] else s[1]:=[6];
4: if a[2] in [0,1,2,3,4,5,6,7,8] then s[1]:=[9] else s[1]:=[0,6,8,9];
5: if a[2] in [0,1,2,3,4,5,6,9] then s[1]:=[8] else s[1]:=[0,6,8,9];
6: if a[2] in [7,8] then s[1]:=[9] else s[1]:=[8];
7: s[1]:=[1,4,8,9];
8: if a[2] in [9] then s[1]:=[1,4,8,9] else s[1]:=[9];
9: s[1]:=[2,5,7,9];
end;
case a[n] of
0: if a[n-1] in [7,8] then s[n]:=[9] else s[n]:=[8];
1: if a[n-1] in [4,5,6] then s[n]:=[9] else s[n]:=[6];
2: if a[n-1] in [4,5,6] then s[n]:=[8] else s[n]:=[6];
4: if a[n-1] in [0,1,2,3,4,5,6,7,8] then s[n]:=[9] else s[n]:=[0,6,8,9];
5: if a[n-1] in [0,1,2,3,4,5,6,9] then s[n]:=[8] else s[n]:=[0,6,8,9];
6: if a[n-1] in [7,8] then s[n]:=[9] else s[n]:=[8];
7: s[n]:=[1,4,8,9];
8: if a[n-1] in [9] then s[n]:=[1,4,8,9] else s[n]:=[9];
9: s[n]:=[2,5,7,9];
end;
for i:=2 to n-1 do
case a[i] of
0: begin
if a[i-1] in [0,1,2,3] then x:=2;
if a[i-1] in [4,5,6] then x:=2;
if a[i-1] in [7,8] then x:=3;
if a[i-1] in [9] then x:=4;
if a[i+1] in [0,1,2,3] then y:=2;
if a[i+1] in [4,5,6] then y:=2;
if a[i+1] in [7,8] then y:=3;
if a[i+1] in [9] then y:=4;
if (x+y=7) then
s[i]:=[3,6,8,9]
else if (x=3)or(y=3) then
s[i]:=[9]
else s[i]:=[8];
end;
1: begin
if a[i-1] in [0,1,2,3] then x:=2;
if a[i-1] in [4,5,6] then x:=3;
if a[i-1] in [7,8] then x:=2;
if a[i-1] in [9] then x:=4;
if a[i+1] in [0,1,2,3] then y:=2;
if a[i+1] in [4,5,6] then y:=3;
if a[i+1] in [7,8] then y:=2;
if a[i+1] in [9] then y:=4;
if (x+y=7) then
s[i]:=[3,6,8,9]
else if (x=3)or(y=3) then
s[i]:=[9]
else s[i]:=[6];
end;
2: begin
if a[i-1] in [0,1,2,3] then x:=2;
if a[i-1] in [4,5,6] then x:=3;
if a[i-1] in [7,8] then x:=4;
if a[i-1] in [9] then x:=2;
if a[i+1] in [0,1,2,3] then y:=2;
if a[i+1] in [4,5,6] then y:=3;
if a[i+1] in [7,8] then y:=4;
if a[i+1] in [9] then y:=2;
if (x+y=7) then
s[i]:=[3,6,8,9]
else if (x=3)or(y=3) then
s[i]:=[8]
else s[i]:=[6];
end;
3: begin
if a[i-1] in [4,5,6] then x:=2;
if a[i-1] in [7,8] then x:=3;
if a[i-1] in [9] then x:=4;
if a[i+1] in [4,5,6] then y:=2;
if a[i+1] in [7,8] then y:=3;
if a[i+1] in [9] then y:=4;
x:=9-x-y;
if x=2 then s[i]:=[6];
if x=3 then s[i]:=[8];
if x=4 then s[i]:=[9];
end;
4: begin
x:=0;
if a[i-1] in [9] then x:=2;
if a[i+1] in [9] then x:=2;
if x=2 then s[i]:=[0,6,8,9] else s[i]:=[9];
end;
5: begin
x:=0;
if a[i-1] in [7,8] then x:=2;
if a[i+1] in [7,8] then x:=2;
if x=2 then s[i]:=[0,6,8,9] else s[i]:=[8];
end;
6: begin
if a[i-1] in [0,1,2,3] then x:=2;
if a[i-1] in [4,5,6] then x:=2;
if a[i-1] in [7,8] then x:=3;
if a[i-1] in [9] then x:=4;
if a[i+1] in [0,1,2,3] then y:=2;
if a[i+1] in [4,5,6] then y:=2;
if a[i+1] in [7,8] then y:=3;
if a[i+1] in [9] then y:=4;
if (x+y=7) then
s[i]:=[0,6,8,9]
else if (x=3)or(y=3) then
s[i]:=[9]
else s[i]:=[8];
end;
7: s[i]:=[1,4,8,9];
8: begin
x:=0;
if a[i-1] in [9] then x:=2;
if a[i+1] in [9] then x:=2;
if x=2 then s[i]:=[1,4,8,9] else s[i]:=[9];
end;
9: s[i]:=[2,5,7,9];
end;
fillchar(cc,sizeof(cc),0);
for i:=1 to n do
for j:=0 to 9 do
if j in s[i] then
begin inc(cc[i]);
dt[i,cc[i]]:=j;
end;
for i:=1 to n do b[i]:=1;
b[0]:=0;
while b[0]=0 do
begin cur:=0;
for i:=n downto 1 do cur:=cur*10+dt[i,b[i]];
if ok[cur]<>0 then
if dp[next-1,ok[xw]]+checkvl(n,cur)>dp[next,ok[cur]] then
dp[next,ok[cur]]:=dp[next-1,ok[xw]]+checkvl(n,cur);
j:=n;
while (j>0)and(b[j]=cc[j]) do begin b[j]:=1; dec(j); end;
inc(b[j]);
end;
end;
function checklastok(n,x1:longint):boolean;
var i,x,y,j,cur,xw:longint;
begin xw:=x1;
for i:=1 to n do
begin a[i]:=x1 mod 10;
x1:=x1 div 10;
end;
case a[1] of
0: if a[2] in [7,8] then s[1]:=[9] else s[1]:=[8];
1: if a[2] in [4,5,6] then s[1]:=[9] else s[1]:=[6];
2: if a[2] in [4,5,6] then s[1]:=[8] else s[1]:=[6];
4: if a[2] in [0,1,2,3,4,5,6,7,8] then s[1]:=[9] else s[1]:=[0,6,8,9];
5: if a[2] in [0,1,2,3,4,5,6,9] then s[1]:=[8] else s[1]:=[0,6,8,9];
6: if a[2] in [7,8] then s[1]:=[9] else s[1]:=[8];
7: s[1]:=[1,4,8,9];
8: if a[2] in [9] then s[1]:=[1,4,8,9] else s[1]:=[9];
9: s[1]:=[2,5,7,9];
end;
case a[n] of
0: if a[n-1] in [7,8] then s[n]:=[9] else s[n]:=[8];
1: if a[n-1] in [4,5,6] then s[n]:=[9] else s[n]:=[6];
2: if a[n-1] in [4,5,6] then s[n]:=[8] else s[n]:=[6];
4: if a[n-1] in [0,1,2,3,4,5,6,7,8] then s[n]:=[9] else s[n]:=[0,6,8,9];
5: if a[n-1] in [0,1,2,3,4,5,6,9] then s[n]:=[8] else s[n]:=[0,6,8,9];
6: if a[n-1] in [7,8] then s[n]:=[9] else s[n]:=[8];
7: s[n]:=[1,4,8,9];
8: if a[n-1] in [9] then s[n]:=[1,4,8,9] else s[n]:=[9];
9: s[n]:=[2,5,7,9];
end;
for i:=2 to n-1 do
case a[i] of
0: begin
if a[i-1] in [0,1,2,3] then x:=2;
if a[i-1] in [4,5,6] then x:=2;
if a[i-1] in [7,8] then x:=3;
if a[i-1] in [9] then x:=4;
if a[i+1] in [0,1,2,3] then y:=2;
if a[i+1] in [4,5,6] then y:=2;
if a[i+1] in [7,8] then y:=3;
if a[i+1] in [9] then y:=4;
if (x+y=7) then
s[i]:=[3,6,8,9]
else if (x=3)or(y=3) then
s[i]:=[9]
else s[i]:=[8];
end;
1: begin
if a[i-1] in [0,1,2,3] then x:=2;
if a[i-1] in [4,5,6] then x:=3;
if a[i-1] in [7,8] then x:=2;
if a[i-1] in [9] then x:=4;
if a[i+1] in [0,1,2,3] then y:=2;
if a[i+1] in [4,5,6] then y:=3;
if a[i+1] in [7,8] then y:=2;
if a[i+1] in [9] then y:=4;
if (x+y=7) then
s[i]:=[3,6,8,9]
else if (x=3)or(y=3) then
s[i]:=[9]
else s[i]:=[6];
end;
2: begin
if a[i-1] in [0,1,2,3] then x:=2;
if a[i-1] in [4,5,6] then x:=3;
if a[i-1] in [7,8] then x:=4;
if a[i-1] in [9] then x:=2;
if a[i+1] in [0,1,2,3] then y:=2;
if a[i+1] in [4,5,6] then y:=3;
if a[i+1] in [7,8] then y:=4;
if a[i+1] in [9] then y:=2;
if (x+y=7) then
s[i]:=[3,6,8,9]
else if (x=3)or(y=3) then
s[i]:=[8]
else s[i]:=[6];
end;
3: begin
if a[i-1] in [4,5,6] then x:=2;
if a[i-1] in [7,8] then x:=3;
if a[i-1] in [9] then x:=4;
if a[i+1] in [4,5,6] then y:=2;
if a[i+1] in [7,8] then y:=3;
if a[i+1] in [9] then y:=4;
x:=9-x-y;
if x=2 then s[i]:=[6];
if x=3 then s[i]:=[8];
if x=4 then s[i]:=[9];
end;
4: begin
x:=0;
if a[i-1] in [9] then x:=2;
if a[i+1] in [9] then x:=2;
if x=2 then s[i]:=[0,6,8,9] else s[i]:=[9];
end;
5: begin
x:=0;
if a[i-1] in [7,8] then x:=2;
if a[i+1] in [7,8] then x:=2;
if x=2 then s[i]:=[0,6,8,9] else s[i]:=[8];
end;
6: begin
if a[i-1] in [0,1,2,3] then x:=2;
if a[i-1] in [4,5,6] then x:=2;
if a[i-1] in [7,8] then x:=3;
if a[i-1] in [9] then x:=4;
if a[i+1] in [0,1,2,3] then y:=2;
if a[i+1] in [4,5,6] then y:=2;
if a[i+1] in [7,8] then y:=3;
if a[i+1] in [9] then y:=4;
if (x+y=7) then
s[i]:=[0,6,8,9]
else if (x=3)or(y=3) then
s[i]:=[9]
else s[i]:=[8];
end;
7: s[i]:=[1,4,8,9];
8: begin
x:=0;
if a[i-1] in [9] then x:=2;
if a[i+1] in [9] then x:=2;
if x=2 then s[i]:=[1,4,8,9] else s[i]:=[9];
end;
9: s[i]:=[2,5,7,9];
end;
fillchar(cc,sizeof(cc),0);
for i:=1 to n do
for j:=0 to 9 do
if j in s[i] then
begin inc(cc[i]);
dt[i,cc[i]]:=j;
end;
for i:=1 to n do if cc[i]<>4 then exit(false);
exit(true);
end;
procedure solve(n:longint);
var all,i,j,count,ans:longint;
begin //0=ruby-emerald 1=ruby-sapphire 2=ruby-diamond 3=ruby-other
//4=emerald-sapphire 5=emerald-diamond 6=emerald-other
//7=sapphire-diamond 8=sapphire-other
//9=diamond-other
all:=1;
for i:=1 to n do all:=all*10;
dec(all);
fillchar(ok,sizeof(ok),0);
count:=0;
for i:=0 to all do
if check(n,i) then
begin inc(count);
d[count]:=i;
ok[i]:=count;
end;
for i:=1 to 7 do
for j:=1 to count do
dp[i,j]:=-maxlongint;
for j:=1 to count do
if checkinit(n,d[j]) then
dp[1,j]:=checkvl(n,d[j]);
for i:=2 to 7 do
for j:=1 to count do
if dp[i-1,j]<>-maxlongint then
expand(n,d[j],i);
for i:=2 to 7 do
begin ans:=-maxlongint;
for j:=1 to count do
if checklastok(n,d[j]) then
if dp[i,j]>ans then
ans:=dp[i,j];
write(ans,' ');
end;
writeln;
end;
var
i:longint;
begin
assign(output,'3861.out');
rewrite(output);
for i:=2 to 7 do solve(i);
close(output);
end.
Followed by: Post your reply here: |
All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator