您的位置:首页 > 其它

ZOJ 3209 Treasure Map

2015-04-24 00:54 169 查看
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3209

dancing links 每个点作为一列。

每个块作为一行。

不知道为什么插节点的时候 如果把循环写成

for(int i = y1+1; i <= y2; i++){      //行
for(int j = x1+1; j <= x2; j++){ //列
      
}
}
然后col = (y-1)*n+x就会超时。


#include <iostream>
#include <cstring>
#include <cstdio>
#include <string>
#include <iomanip>
using namespace std;
int T, n, m, p, x1, y1, x2, y2;
#define maxn 510*35*35
int R[maxn], L[maxn], U[maxn], D[maxn];
int H[maxn], C[maxn], colsum[999];
int head, cnt, ans;
void addnode(int i, int j, int h, int rowhead, int sum, int pre){
int col = j+(i-1)*m; //cout<<col<<" ";
cnt++;

H[cnt] = h; C[cnt] = col;
if(sum == 1){
R[cnt] = cnt; L[cnt] = cnt;
}
else if(sum == 2){
R[pre] = cnt; R[cnt] = pre;
L[pre] = cnt; L[cnt] = pre;
}
else{
R[cnt] = rowhead; R[pre] = cnt;
L[cnt] = pre; L[rowhead] = cnt;
}

D[U[col]] = cnt;
U[cnt] = U[col];
D[cnt] = col;
U[col] = cnt;

colsum[col]++;

}
void init(){
head = cnt = 0;
ans = 510;  //最多就是500块。
R[head] = 1; L[head] = n*m; U[head] = head; D[head] = head;
H[head] = 0; C[head] = 0;
memset(colsum, 0, sizeof(colsum));
for(int i = 1; i <= n*m; i++){
cnt++;
U[cnt] = D[cnt] = cnt;
H[cnt] = 0; C[cnt] = i;
if(i == n*m){
R[cnt-1] = cnt; L[cnt] = cnt-1; R[cnt] = head;
}
else{
R[cnt-1] = cnt; L[cnt] = cnt-1;
}
}
for(int cc = 1; cc <= p; cc++){
scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
int sum = 0, rowhead = -1, pre;
for(int i = x1+1; i <= x2; i++){      //行
for(int j = y1+1; j <= y2; j++){ //列
sum++;
addnode(i, j ,cc, rowhead, sum, pre);
if(rowhead == -1) rowhead = cnt;
pre = cnt;
}
}
}
}
void remove(int c){
R[L[c]] = R[c]; L[R[c]] = L[c];
for(int i = D[c]; i != c; i = D[i]){
for(int j = R[i]; j != i; j = R[j]){
U[D[j]] = U[j]; D[U[j]] = D[j];
colsum[C[j]]--;
}
}
}
void resume(int c){
R[L[c]] = c; L[R[c]] = c;
for(int i = D[c]; i != c; i = D[i]){
for(int j = R[i]; j != i; j = R[j]){
U[D[j]] = j; D[U[j]] = j;
colsum[C[j]]++;
}
}
}
void dance(int k){
if(k >= ans) return;
int c = R[head];
if(c == head){
ans = k;
return;
}
int min = 9999999;
for(int i = R[head]; i != head; i = R[i]){
if(colsum[i] <= min){
min = colsum[i]; c = i;
}
}
remove(c);
for(int i = D[c]; i != c; i = D[i]){
for(int j = R[i]; j != i; j = R[j]) remove(C[j]);
dance(k+1);
for(int j = L[i]; j != i; j = L[j]) resume(C[j]); //要写成L
}
resume(c);
return ;
}
int main(){
scanf("%d", &T);
while(T--){
scanf("%d%d%d", &n, &m, &p); //n是列,m是行。
init();
dance(0);
if(ans == 510) printf("-1\n");
else printf("%d\n", ans);
}

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