您的位置:首页 > 其它

usaco Party Lamps report

2015-09-04 15:53 337 查看
这道题核心的算法是搜索,然后用状态压缩(位运算)来优化。

有必要好好体会一下位运算具体的实施过程,把一些看起来不太容易用位运算做的问题使用其来提速。

换句话讲,每一个步骤都考虑到其最优的可能对于整体性能的提升是很重要的。

首先1《《a,可以表示一个在第a位置上是1的数,如果现在用一个状态数b,b&a用来检测b的第a位置上是否为1.

|的作用往往体现在添加状态,b|a可以使第a位变成1,无论之前是什么。

还要记住一个^异或运算符,自己造好需要的运算。检测一下它的可行性就好。

标准答案写的比我的精简多了,所以我就不贴自己的了,直接附上标程以供参考:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

#define MAXLAMP 6
#define LAMPMASK ((1<<MAXLAMP)-1)

int nlamp;
int nswitch;
int ison;
int known;

int poss[1<<MAXLAMP];

int flip[4] = {
LAMPMASK, /* flip all lights */
LAMPMASK & 0xAA, /* flip odd lights */
LAMPMASK & 0x55, /* flip even lights */
LAMPMASK & ((1<<(MAXLAMP-1))|(1<<(MAXLAMP-4))) /* lights 1, 4 */
};

/*
* Starting with current light state ``lights'', flip exactly n switches
* with number >= i.
*/
void
search(int lights, int i, int n)
{
if(n == 0) {
if((lights & known) == ison)
poss[lights] = 1;
return;
}

for(; i<4; i++)
search(lights ^ flip[i], i+1, n-1);
}

void
printseq(FILE *fout, int lights)
{
int i;
char s[100+1];

for(i=0; i<nlamp; i++)
s[i] = (lights & (1<<(MAXLAMP-1 - i%MAXLAMP))) ? '1' : '0';
s[nlamp] = '\0';
fprintf(fout, "%s\n", s);
}

void
main(void)
{
FILE *fin, *fout;
int a, i, impossible;

fin = fopen("lamps.in", "r");
fout = fopen("lamps.out", "w");
assert(fin != NULL && fout != NULL);

fscanf(fin, "%d %d", &nlamp, &nswitch);

for(;;) {
fscanf(fin, "%d", &a);
if(a == -1)
break;
a = MAXLAMP-1 - (a-1) % MAXLAMP;
ison |= 1<<a;
known |= 1<<a;
}

for(;;) {
fscanf(fin, "%d", &a);
if(a == -1)
break;
a = MAXLAMP-1 - (a-1) % MAXLAMP;
assert((ison & (1<<a)) == 0);
known |= 1<<a;
}

if(nswitch > 4)
if(nswitch%2 == 0)
nswitch = 4;
else
nswitch = 3;

for(; nswitch >= 0; nswitch -= 2)
search(LAMPMASK, 0, nswitch);

impossible = 1;
for(i=0; i<(1<<MAXLAMP); i++) {
if(poss[i]) {
printseq(fout, i);
impossible = 0;
}
}
if(impossible)
fprintf(fout, "IMPOSSIBLE\n");

exit(0);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  usaco 算法