您的位置:首页 > 其它

JZOJ1265.【USACO题库】2.2.4 Party Lamps派对灯

2017-06-17 21:56 465 查看
题目描述

在IOI98的节日宴会上,我们有N(10<=N<=100)盏彩色灯,他们分别从1到N被标上号码。

这些灯都连接到四个按钮:

按钮1:当按下此按钮,将改变所有的灯:本来亮着的灯就熄灭,本来是关着的灯被点亮。

按钮2:当按下此按钮,将改变所有奇数号的灯。

按钮3:当按下此按钮,将改变所有偶数号的灯。

按钮4:当按下此按钮,将改变所有序号是3*K+1(K>=0)的灯。例如:1,4,7…

一个计数器C记录按钮被按下的次数。

当宴会开始,所有的灯都亮着,此时计数器C为0。

你将得到计数器C(0<=C<=10000)上的数值和经过若干操作后所有灯的状态。写一个程序去找出所有灯最后可能的与所给出信息相符的状态,并且没有重复。

PROGRAM NAME: lamps

INPUT FORMAT

不会有灯会在输入中出现两次。

第一行: N。

第二行: C最后显示的数值。

第三行: 最后亮着的灯,用一个空格分开,以-1为结束。

第四行: 最后关着的灯,用一个空格分开,以-1为结束。

SAMPLE INPUT (file lamps.in)

10

1

-1

7 -1

在这个样例中,有10盏灯,只有1个按钮被按下。最后7号灯是关着的。

OUTPUT FORMAT

每一行是所有灯可能的最后状态(没有重复)。每一行有N个字符,第1个字符表示1号灯,最后一个字符表示N号灯。0表示关闭,1表示亮着。这些行必须从小到大排列(看作是二进制数)。

如果没有可能的状态,则输出一行’IMPOSSIBLE’。

SAMPLE OUTPUT (file lamps.out)

0000000000

0101010101

0110110110

在这个样例中,有三种可能的状态:

所有灯都关着

1,4,7,10号灯关着,2,3,5,6,8,9亮着。

1,3,5,7,9号灯关着,2, 4, 6, 8, 10亮着。

输入

输出

样例输入

样例输出

数据范围限制

首先这又是一道IOI真题~

思路:

采取暴力的思想

但直接来绝对时间爆炸

那么考虑优化:

优化1:

通过手算不难发现,无论怎么改变,都是六个一循环的

于是乎我们可以只改变六个,最后再判断整段,节省时间

上面的优化完全不够?

那么下面这个优化才是AC关键

优化2:

对于任意一个c,若它大于等于8:

为偶数就为4,否则就为5

严谨证明过程略,但这个东东一定是正确的

于是乎两个优化到手,AC轻松揣进兜~

代码(不知怎么,这段code打得很难看):

type
arra=array[0..6]of longint;
const
change:array[1..4,1..6]of longint=
(
(1,1,1,1,1,1),
(1,0,1,0,1,0),
(0,1,0,1,0,1),
(1,0,0,1,0,0)
);
var
n,c,i,x,tot:longint;
open,off:array[0..100]of boolean;
ans:array[0..10000]of string;
temp:arra;
procedure qsort(l,r:longint);
var
i,j:longint;
mid,t:string;
begin
i:=l;
j:=r;
mid:=ans[(l+r)div 2];
repeat
while ans[i]<mid do inc(i);
while ans[j]>mid do dec(j);
if i<=j then
begin
t:=ans[i];
ans[i]:=ans[j];
ans[j]:=t;
inc(i);
dec(j);
end;
until i>j;
if l<j then qsort(l,j);
if i<r then qsort(i,r);
end;
function judge(t:arra):boolean;
var
i,j:longint;
begin
for i:=1 to n do
begin
j:=i mod 6;
if j=0 then j:=6;
if (open[i])and(t[j]=0)or(off[i])and(t[j]=1)then exit(false);
end;
exit(true);
end;
procedure dfs(x:longint;fx:arra);
var
i,j:longint;
flag:boolean;
st:string;
xx:arra;
begin
if x>c then
begin
if judge(fx) then
begin
st:='';
for i:=1 to n do
begin
j:=i mod 6;
if j=0 then j:=6;
if fx[j]=1 then st:=st+'1'
else st:=st+'0';
end;
flag:=true;
for i:=1 to tot do
if ans[i]=st then
begin
flag:=false;
break;
end;
if flag then
begin
inc(tot);
ans[tot]:=st;
end;
end;
exit;
end;
for j:=1 to 4 do
begin
for i:=1 to 6 do
xx[i]:=(fx[i]+change[j,i])mod 2;
dfs(x+1,xx);
end;
end;
begin
read(n,c,x);
for i:=1 to 6 do temp[i]:=1;
while x<>-1 do
begin
open[x]:=true;
read(x);
end;
read(x);
while x<>-1 do
begin
off[x]:=true;
read(x);
end;
if c>=8 then
begin
if c mod 2=0 then c:=4
else c:=5;
end;
dfs(1,temp);
if tot=0 then writeln('IMPOSSIBLE')
else
begin
qsort(1,tot);
for i:=1 to tot do writeln(ans[i]);
end;
end.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: