FZU 1686 神龙的难题 (DLX)
Appoint description:
Description
这是个剑与魔法的世界.英雄和魔物同在,动荡和安定并存.但总的来说,库尔特王国是个安宁的国家,人民安居乐业,魔物也比较少.但是.总有一些魔物不时会进入城市附近,干扰人民的生活.就要有一些人出来守护居民们不被魔物侵害.魔法使艾米莉就是这样的一个人.她骑着她的坐骑,神龙米格拉一起消灭干扰人类生存的魔物,维护王国的安定.艾米莉希望能够在损伤最小的前提下完成任务.每次战斗前,她都用时间停止魔法停住时间,然后米格拉他就可以发出火球烧死敌人.米格拉想知道,他如何以最快的速度消灭敌人,减轻艾米莉的负担.
Input
数据有多组,你要处理到EOF为止.每组数据第一行有两个数,n,m,(1<=n,m<=15)表示这次任务的地区范围. 然后接下来有n行,每行m个整数,如为1表示该点有怪物,为0表示该点无怪物.然后接下一行有两个整数,n1,m1 (n1<=n,m1<=m)分别表示米格拉一次能攻击的行,列数(行列不能互换),假设米格拉一单位时间能发出一个火球,所有怪物都可一击必杀.
Output
输出一行,一个整数,表示米格拉消灭所有魔物的最短时间.
Sample Input
4 4 1 0 0 1 0 1 1 0 0 1 1 0 1 0 0 1 2 2 4 4 0 0 0 0 0 1 1 0 0 1 1 0 0 0 0 0 2 2
Sample Output
4 1
做DLX做得我都恶心了,每次都是TTTTTTT,这题T了两天,没话说了。
把每个有怪物的点作为列,每次攻击能达到的区域作为行,问题就转化为最少选取多少行可以使得所有列都被覆盖。重复覆盖,A*剪枝。
1 #include <iostream> 2 #include <string> 3 #include <cstring> 4 #include <cstdio> 5 using namespace std; 6 7 const int HEAD = 0; 8 const int SIZE = 20 * 20 * 20 * 20; 9 const int INF = 0x7fffffff; 10 bool VIS[SIZE]; 11 int U[SIZE],D[SIZE],L[SIZE],R[SIZE],C[SIZE],S[SIZE],LOC[SIZE]; 12 int COUNT,ANS; 13 int N,M; 14 15 int h(void); 16 void ini(void); 17 void dancing(int); 18 void remove(int); 19 void resume(int); 20 void debug(void); 21 int main(void) 22 { 23 int n,m; 24 25 while(scanf("%d%d",&N,&M) != EOF) 26 { 27 ini(); 28 scanf("%d%d",&n,&m); 29 30 for(int i = 1;i + n - 1 <= N;i ++) 31 for(int j = 1;j + m - 1 <= M;j ++) 32 { 33 int first = COUNT; 34 for(int k = 0;k < n;k ++) 35 for(int l = 0;l < m;l ++) 36 { 37 int loc = LOC[(i + k - 1) * M + j + l]; 38 if(loc != -1) 39 { 40 L[COUNT] = COUNT - 1; 41 R[COUNT] = COUNT + 1; 42 U[COUNT] = U[loc]; 43 D[COUNT] = loc; 44 45 D[U[loc]] = COUNT; 46 U[loc] = COUNT; 47 S[loc] ++; 48 C[COUNT] = loc; 49 COUNT ++; 50 } 51 } 52 if(first != COUNT) 53 { 54 L[first] = COUNT - 1; 55 R[COUNT - 1] = first; 56 } 57 } 58 dancing(0); 59 printf("%d\n",ANS); 60 } 61 62 return 0; 63 } 64 65 void ini(void) 66 { 67 ANS = INF; 68 COUNT = 1; 69 int box; 70 71 for(int i = 1;i <= N;i ++) 72 for(int j = 1;j <= M;j ++) 73 { 74 scanf("%d",&box); 75 if(box) 76 { 77 L[COUNT] = COUNT - 1; 78 R[COUNT] = COUNT + 1; 79 U[COUNT] = D[COUNT] = COUNT; 80 C[COUNT] = COUNT; 81 S[COUNT] = 0; 82 LOC[(i - 1) * M + j] = COUNT; 83 COUNT ++; 84 } 85 else 86 LOC[(i - 1) * M + j] = -1; 87 } 88 if(COUNT != 1) 89 { 90 R[COUNT - 1] = HEAD; 91 L[HEAD] = COUNT - 1; 92 R[HEAD] = 1; 93 } 94 else 95 R[HEAD] = L[HEAD] = HEAD; 96 } 97 98 void dancing(int k) 99 { 100 if(R[HEAD] == HEAD) 101 { 102 ANS = ANS < k ? ANS : k; 103 return ; 104 } 105 if(k + h() >= ANS) 106 return ; 107 108 int c = R[HEAD]; 109 for(int i = L[HEAD];i != HEAD;i = L[i]) 110 if(S[i] < S[c]) 111 c = i; 112 113 for(int i = D[c];i != c;i = D[i]) 114 { 115 remove(i); 116 for(int j = R[i];j != i;j = R[j]) 117 remove(j); 118 dancing(k + 1); 119 for(int j = L[i];j != i;j = L[j]) 120 resume(j); 121 resume(i); 122 } 123 124 return ; 125 } 126 127 void remove(int c) 128 { 129 for(int i = D[c];i != c;i = D[i]) 130 { 131 L[R[i]] = L[i]; 132 R[L[i]] = R[i]; 133 } 134 } 135 136 void resume(int c) 137 { 138 for(int i = U[c];i != c;i = U[i]) 139 { 140 L[R[i]] = i; 141 R[L[i]] = i; 142 } 143 } 144 145 int h(void) 146 { 147 for(int i = R[HEAD];i;i = R[i]) 148 VIS[i] = false; 149 150 int sum = 0; 151 for(int i = R[HEAD];i != HEAD;i = R[i]) 152 if(!VIS[i]) 153 { 154 sum ++; 155 VIS[i] = true; 156 for(int j = D[i];j != i;j = D[j]) 157 for(int k = R[j];k != j;k = R[k]) 158 VIS[C[k]] = true; 159 } 160 161 return sum; 162 }