Online JudgeProblem SetAuthorsOnline ContestsUser
Web Board
Home Page
F.A.Qs
Statistical Charts
Problems
Submit Problem
Online Status
Prob.ID:
Register
Update your info
Authors ranklist
Current Contest
Past Contests
Scheduled Contests
Award Contest
User ID:
Password:
  Register

不会构造,于是直接状压DP打表。附代码及解题报告。

Posted by xuhaoran510 at 2011-07-08 08:57:58 on Problem 3861 and last updated at 2011-07-08 08:58:18
状态的表示:状态只与前两行的宝石有关。最朴素的表示就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:
User ID:
Password:
Title:

Content:

Home Page   Go Back  To top


All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator