FZU 1686 神龙的难题

来源:互联网 发布:网络社交的利与弊800 编辑:程序博客网 时间:2024/05/17 08:01

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重复覆盖

#include<cstdio>#include<vector>#include<cmath>#include<cstring>#include<algorithm>using namespace std;typedef long long ll;const ll maxn = 25;int n, m, x, y, mp[maxn][maxn], t1, t2;inline void read(int &ret){char c;do {c = getchar();} while (c < '0' || c > '9');ret = c - '0';while ((c = getchar()) >= '0' && c <= '9')ret = ret * 10 + (c - '0');}struct DLX{#define maxn 10005#define F(i,A,s) for (int i=A[s];i!=s;i=A[i])int L[maxn], R[maxn], U[maxn], D[maxn];int row[maxn], col[maxn], ans[maxn], cnt[maxn];int n, m, num, sz;void add(int now, int l, int r, int u, int d, int x, int y){L[now] = l;R[now] = r;U[now] = u;D[now] = d;   row[now] = x;  col[now] = y;}void reset(int n, int m, int x){if (x) num = 0x7FFFFFFF; else num = 0;this->n = n;this->m = m;for (int i = 0; i <= m; i++){add(i, i - 1, i + 1, i, i, 0, i);cnt[i] = 0;}L[0] = m; R[m] = 0; sz = m + 1;}void insert(int x, int y){int ft = sz - 1;if (row[ft] != x){add(sz, sz, sz, U[y], y, x, y);U[D[sz]] = sz; D[U[sz]] = sz;}else{add(sz, ft, R[ft], U[y], y, x, y);R[L[sz]] = sz; L[R[sz]] = sz;U[D[sz]] = sz; D[U[sz]] = sz;}++cnt[y];++sz;}//精确覆盖void remove(int now){R[L[now]] = R[now];L[R[now]] = L[now];F(i, D, now) F(j, R, i){D[U[j]] = D[j];U[D[j]] = U[j];--cnt[col[j]];}}void resume(int now){F(i, U, now)F(j, L, i){D[U[j]] = j;U[D[j]] = j;++cnt[col[j]];}R[L[now]] = now;L[R[now]] = now;}int dfs(int x){if (!R[0]) return 1;int now = R[0];F(i, R, 0) if (cnt[now]>cnt[i]) now = i;remove(now);F(i, D, now){ans[x] = row[i];F(j, R, i) remove(col[j]);if (dfs(x + 1)) return 1;F(j, L, i) resume(col[j]);}resume(now);return 0;}//精确覆盖//重复覆盖void Remove(int now){F(i, D, now){L[R[i]] = L[i];R[L[i]] = R[i];}}void Resume(int now){F(i, U, now) L[R[i]] = R[L[i]] = i;}int vis[maxn];int flag[maxn];int A(){int dis = 0;F(i, R, 0) vis[i] = 0;F(i, R, 0) if (!vis[i]){dis++;vis[i] = 1;F(j, D, i) F(k, R, j) vis[col[k]] = 1;}return dis;}void Dfs(int x){if (!R[0]) num = min(num, x);else if (x + A()<num){int now = R[0];F(i, R, 0) if (cnt[now]>cnt[i]) now = i;F(i, D, now){Remove(i); F(j, R, i) Remove(j);Dfs(x + 1);F(j, L, i) Resume(j); Resume(i);}}}//重复覆盖}dlx;int main(){//read(T);while (scanf("%d%d", &n, &m) == 2){t1 = t2 = 0;for (int i = 1; i <= n; ++i)for (int j = 1; j <= m; ++j){ scanf("%d", &mp[i][j]); t2 += mp[i][j];if (mp[i][j]) mp[i][j] = t2;}scanf("%d%d", &x, &y);t1 = (n - x + 1)*(m - y + 1);dlx.reset(t1, t2, 1);t1 = 0;for (int i = 1; i + x - 1 <= n; i++)for (int j = 1; j + y - 1 <= m; j++){t1++;for (int x1 = 0; x1 < x; x1++)for (int y1 = 0; y1 < y; y1++)if (mp[i + x1][j + y1]) dlx.insert(t1, mp[i + x1][j + y1]);}dlx.Dfs(0);printf("%d\n", dlx.num);}return 0;}



0 0
原创粉丝点击