题目:这是个剑与魔法的世界.英雄和魔物同在,动荡和安定并存.但总的来说,库尔特王国是个安宁的国家,人民安居乐业,魔物也比较少.但是.总有一些魔物不时会进入城市附近,干扰人民的生活.就要有一些人出来守护居民们不被魔物侵害.魔法使艾米莉就是这样的一个人.她骑着她的坐骑,神龙米格拉一起消灭干扰人类生存的魔物,维护王国的安定.艾米莉希望能够在损伤最小的前提下完成任务.每次战斗前,她都用时间停止魔法停住时间,然后米格拉他就可以发出火球烧死敌人.米格拉想知道,他如何以最快的速度消灭敌人,减轻艾米莉的负担.
input:数据有多组,你要处理到EOF为止.每组数据第一行有两个数,n,m,(1<=n,m<=15)表示这次任务的地区范围. 然后接下来有n行,每行m个整数,如为1表示该点有怪物,为0表示该点无怪物.然后接下一行有两个整数,n1,m1 (n1<=n,m1<=m)分别表示米格拉一次能攻击的行,列数(行列不能互换),假设米格拉一单位时间能发出一个火球,所有怪物都可一击必杀.
output:输出一行,一个整数,表示米格拉消灭所有魔物的最短时间.
代码:
#pragma comment(linker, "/STACK:1024000000,1024000000") #include<iostream> #include<algorithm> #include<cstdio> #include<cmath> #include<cstring> #include<string> #include<vector> #include<map> #include<set> #include<queue> #include<stack> #include<list> #include<numeric> using namespace std; #define PI acos(-1.0) #define LL long long #define ULL unsigned long long #define INF 0x3f3f3f3f #define mm(a,b) memset(a,b,sizeof(a)) #define PP puts("*********************"); template<class T> T f_abs(T a){ return a > 0 ? a : -a; } template<class T> T gcd(T a, T b){ return b ? gcd(b, a%b) : a; } template<class T> T lcm(T a,T b){return a/gcd(a,b)*b;} // 0x3f3f3f3f3f3f3f3f // 0x3f3f3f3f int limit;//重复覆盖时使用,行数选择的最大数目 struct DLX { const static int ROW = 1003, COL = 1003, SIZE = ROW * COL; int L[SIZE], R[SIZE], U[SIZE], D[SIZE]; //模拟指针 int col[SIZE], row[SIZE]; //所在列 所在行 int visn, visited[COL]; //用于估价函数 int sel[ROW], seln; //选择的行 int sz[COL]; //列元素数 int total/*节点编号*/, H[ROW]; void init(int clen) { //初始化列头指针 for(int i = 0; i <= clen; ++i) { L[i] = i - 1; R[i] = i + 1; U[i] = D[i] = i; sz[i] = 0; } for(int i=0;i<ROW;i++) H[i]=-1; for(int i=0;i<COL;i++) visited[i]=0; visn = 0; //用于重复覆盖的A*剪枝 L[0] = clen; R[clen] = 0; total = clen + 1; } void link(int r, int c) {//行列都是从下标1开始 U[total] = c; D[total] = D[c]; U[D[c]] = total; D[c] = total; if(H[r] < 0) H[r] = L[total] = R[total] = total; else { L[total] = H[r]; R[total] = R[H[r]]; L[R[H[r]]] = total; R[H[r]] = total; } sz[c]++; col[total] = c; row[total++] = r; } //-------------------- 精确覆盖 ------------------------- void remove(const int &c) { //删除c列上所有1元素所在的行 L[R[c]] = L[c]; R[L[c]] = R[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], --sz[col[j]]; } void resume(const int &c) { //恢复c列上所有1元素所在的行 R[L[c]] = L[R[c]] = c; for(int i = U[c]; i != c; i = U[i]) for(int j = L[i]; j != i; j = L[j]) ++sz[col[U[D[j]] = D[U[j]] = j]]; } bool dance(int now) { if(R[0] == 0) { seln = now; return true; } int c=R[0], i, j; for(i = R[0]; i != 0; i = R[i]) //选择元素最少的列c if(sz[c] > sz[i]) c = i; remove(c); for(i = D[c]; i != c; i = D[i]) { //删除与c相连的行i for(j = R[i]; j != i; j = R[j]) //删除行元素所在的列j remove(col[j]); sel[now] = row[i]; //选择此行 保存行号 if(dance(now + 1)) { //对于不同的题 这个地方常常需要改动 return true; } for(j = L[i]; j != i; j = L[j]) resume(col[j]); } resume(c); return false; } //-------------------- 重复覆盖 ------------------------- void _remove(const int &c) { for(int i = D[c]; i != c; i = D[i]) L[R[i]] = L[i], R[L[i]] = R[i]; } void _resume(const int &c) { for(int i = U[c]; i != c; i = U[i]) L[R[i]] = R[L[i]] = i; } int Astar(){ //估价函数 int res = 0; ++visn; for(int i = R[0]; i != 0; i = R[i]) { if(visited[i] != visn) { ++res; visited[i] = visn; for(int j = D[i]; j != i; j = D[j]) for(int k = R[j]; k != j; k = R[k]) visited[col[k]] = visn; } } return res; } void _dance(int now) { if(now + Astar() >= limit){ return; } if(R[0] == 0){ limit=min(limit,now); return; } int c=R[0], i, j; for(i = R[0]; i != 0; i = R[i]) //选择元素最少的列c if(sz[c] > sz[i]) c = i; for(i = D[c]; i != c; i = D[i]) { _remove(i); for(j = R[i]; j != i; j = R[j]) _remove(j); _dance(now + 1); for(j = L[i]; j != i; j = L[j]) _resume(j); _resume(i); } } }dl; int arr[20][20]; int main(){ int n,m,n1,m1; while(~scanf("%d%d",&n,&m)){ int r=1,c=0; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++){ scanf("%d",&arr[i][j]); if(arr[i][j]) arr[i][j]=++c; } dl.init(c); scanf("%d%d",&n1,&m1); for(int i=1;i+n1-1<=n;i++) for(int j=1;j+m1-1<=m;j++){ int flag=0; for(int k=i;k<=i+n1-1;k++) for(int t=j;t<=j+m1-1;t++){ if(arr[k][t]>0){ dl.link(r,arr[k][t]); flag=1; } } if(flag) r++; } limit=INF; dl._dance(0); printf("%d\n",limit); } return 0; }