您的位置:首页 > 其它

uva 10318 Security Panel (dfs+剪枝)

2013-02-26 21:44 288 查看
uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1259

  压缩Panel的全部状态,预处理出每个位置的变化,然后dfs搜索全部情况。不过这样是会超时的,所以我在搜索的过程中加上剪枝,预判出之前的状态是否能够使得最后整个Panel充满,如果不能就尽早跳出搜索。加上小小的一个剪枝,速度提升估计了不下1000倍,由原来的超时,最后只要0.008s就完成了!

代码如下:

View Code

#define REP(i, n) for (int i = 0; i < (n); i++)
#define REP_1(i, n) for (int i = 1; i <= (n); i++)

const int dir[9][2] = { {-1, -1}, {-1, 0}, {-1, 1}, {0, -1}, {0, 0}, {0, 1}, {1, -1}, {1, 0}, {1, 1}};
char buf[3][4];
LL pat[25], ok[6];

void pntPat(LL n) {
printf("~~~~~ %lld ~~~~~~\n", n);
DEC(i, 63, 0) {
if (n & (1ll << i)) putchar('1');
else putchar('0');
if ((i & 7) == 0) puts("");
}
}

void makePat(int n, int m) {
int t = (1 << m) - 1 << 1;
REP(i, n + 1) {
ok[i] = 0;
REP(j, i) {
ok[i] |= t;
ok[i] <<= 8;
}
//        pntPat(ok[i]);
}
REP(i, n) {
REP(j, m) {
int id = i * m + j;
pat[id] = 0;
REP(k, 9) {
int x = dir[k][0] + i + 1, y = dir[k][1] + j + 1;
if (buf[k / 3][k % 3] == '*') pat[id] |= 1ll << x * 8 + y;
}
//            cout << id << endl;
//            pntPat(pat[id]);
}
}
}

int rec[30], cnt;

bool dfs(LL cur, int pos, int end, int n, int m) {
if ((cur & ok
) == ok
) return true;
if (pos >= end) return false;
int t = pos / m - 1;
//    cout << pos << ends << m << ends << t << endl;
if (t > 0 && (cur & ok[t]) != ok[t]) return false;
if (dfs(cur, pos + 1, end, n, m)) return true;
rec[cnt++] = pos + 1;
if (dfs(cur ^ pat[pos], pos + 1, end, n, m)) return true;
cnt--;
return false;
}

void work(int n, int m) {
makePat(n, m);
cnt = 0;
if (dfs(0, 0, n * m, n, m)) {
REP(i, cnt) {
if (i) putchar(' ');
printf("%d", rec[i]);
}
puts("");
} else {
puts("Impossible.");
}
}

int main() {
//    freopen("in", "r", stdin);
int n, m, cas = 1;
while (~scanf("%d%d", &n, &m) && (n || m)) {
REP(i, 3) scanf("%s", buf[i]);
printf("Case #%d\n", cas++);
work(n, m);
}
return 0;
}


——written by Lyon
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: