POJ 1084 搜索(IDA*)
来源:互联网 发布:番茄鸡蛋打卤面 知乎 编辑:程序博客网 时间:2024/05/17 23:08
题意:给一个由(n+1)*n*2根火柴棒构成的边长为n正方形,每根火柴棒都有编号,已经删去了k根火柴棒,问至少再删多少根火柴棒可以破坏掉所有正方形。 【刘汝佳:《算法竞赛入门经典(第二版)》 P213】
【小吐槽】
感觉做这道题的历程真是哔了狗了。一开始自己写了个暴搜果断就T了,主要是判断每个正方形存在与否的方法太暴力。之后在网上看到很多人都写的DLX,被如何记录正方形存在的方式恶心到的我下狠心决定学一学DLX。一开始看刘汝佳叔叔的书,懂了大概原理,不过他的书上的代码是精确覆盖的,而这道题是可重复覆盖。所以自己得yy代码,yy+copy网上其他。然而被DLX搞了2天时间,还是有问题,写出来的样例都过不了,哎,还是自己太弱的过。暂时还不适合学这种高大上的东西T^T。无奈了,调DLX代码调的头疼了,决定再写一遍IDA*,沿用了一些表示正方形的特殊技巧,刚刚写完之后抱着肯定会Wa的心态随便交了一下,0ms AC。
那么就是说,这道题我是用的是IDA*,并没有用高大上的舞蹈链。
估价函数还是很好想的,麻烦就麻烦在如何判断在一个状态下还剩哪些正方形。感觉对于乱搞能力强的这个问题都不是事。
我们开两个数组stick[][], square[][] (我用的是vector), stick[i]表示的是需要编号为i的木棒的正方形有哪些,square[i]表示的是编号为i的正方形需要的木棒有哪些。
exi[i]表示的是编号i的正方形是否存在:exi[i] == 0, 存在;每删去该正方形上的一根火柴,exi[i]–。这么做就解决了递归、回溯的问题。
观察一下木棒的编号规律,提前预处理出来正方形们以及木棒们(square,stick两个数组),开始搜索,找到一个还存在的正方形,枚举删除它的哪一根木棒,递归。为了节省时间,要找还存在的边长最小的正方形,这个在我们预处理square数组时,加入正方形的顺序就可以搞定。
估价函数:对于当前一个状态,枚举每个正方形是否存在,如果存在,就删除它的所有木棍,同时res++,然后继续枚举,最后返回res。 这个估价函数和poj 2032 IDA*做法用的那个估价函数很相似。
#include <cstdio>#include <algorithm>#include <cstring>#include <vector>using namespace std;int T, n, k, totstick, totsquare, neibor, ans, maxd, exi[65], temp[65];vector <int> stick[65]; // squares that need stick[i]vector <int> square[65]; // sticks that square[i] needint h(){ int res = 0; for(int i = 1; i <= totsquare; i++) temp[i] = exi[i]; for(int i = 1; i <= totsquare; i++) if(!temp[i]) { res ++; temp[i] -= square[i].size(); for(int j = 0; j < square[i].size(); j++) for(int l = 0; l < stick[square[i][j]].size(); l++) { temp[stick[square[i][j]][l]] --; } } return res;}bool dfs(int sum){ if(sum+h() >= maxd) return 0; int tmp = 1; while(exi[tmp] < 0 && tmp <= totsquare) tmp++; // choose a square (tmp) if(tmp > totsquare) {ans = min(sum, ans); return 1;} for(int i = 0; i < square[tmp].size(); i++) // choose which in tmp to destroy { int sti = square[tmp][i]; for(int j = 0; j < stick[sti].size(); j++) exi[stick[sti][j]]--; if(dfs(sum+1)) return 1; for(int j = 0; j < stick[sti].size(); j++) exi[stick[sti][j]]++; } return 0;}int main(){ scanf("%d", &T); while(T--) { scanf("%d %d", &n, &k); totstick = (n+1)*n*2; totsquare = 0; neibor = n*2+1; for(int i = 1; i < 65; i++) { stick[i].clear(); square[i].clear(); } for(int sz = 1; sz <= n; sz++) for(int i = 1; (i-1)/neibor+sz <= n; i += neibor) for(int j = i; j-i+sz <= n; j++) { totsquare ++; for(int l = j; l-j < sz; l++) { square[totsquare].push_back(l); square[totsquare].push_back(l+sz*neibor); stick[l].push_back(totsquare); stick[l+sz*neibor].push_back(totsquare); } for(int l = j+n; (l-j-sz)/neibor < sz; l += neibor) { square[totsquare].push_back(l); square[totsquare].push_back(l+sz); stick[l].push_back(totsquare); stick[l+sz].push_back(totsquare); } } memset(exi, 0, sizeof exi); for(int i = 1; i <= k; i++) { int t; scanf("%d", &t); for(int j = 0; j < stick[t].size(); j++) { exi[stick[t][j]]--; } totstick --; } ans = totstick; for(maxd = 1; ; maxd++) if(dfs(0)) break; printf("%d\n", ans); } return 0;}
- POJ 1084 搜索(IDA*)
- POJ 2286 搜索 (IDA*)
- POJ 2032 搜索 (IDA*) 或 DLX
- The Rotation Game (poj 2286 搜索IDA*)
- HDU1685Booksort(IDA* 搜索)
- IDA*(poj 2286)
- POJ 3460 Booksort (IDA*)
- POJ 2286 The Rotation Game 搜索-IDA*+迭代加深
- 搜索(IDA*)HOJ The Rotation Game
- HDU 4127 Flood-it!(IDA*搜索)
- HDU 1560 DNA sequence(IDA*搜索)
- 迭代加深搜索 (IDA*)
- poj 3134 Power Calculus (IDA*)
- POJ - 2286 - The Rotation Game (IDA*)
- POJ 2286 The Rotation Game(IDA*)
- 搜索算法:IDA*算法
- 搜索算法:IDA*算法
- 搜索,A* IDA*
- Codeforces Round #325 (Div. 2) A && B
- 互联网创业必备工具盘点
- iOSh中多线程的使用
- “深度学习”学习笔记之深度信念网络 Deep Belief Network(DB)
- 那些在学习iOS开发前就应该知道的事(part 1)
- POJ 1084 搜索(IDA*)
- Android小知识——xml、shape知识点记录1
- 免费好软件推荐之EZDML
- ARC, MRC 的混编
- OpenStack云王者归来---第一章OpenStack概述
- 使用通知机制,在dismissViewControllerAnimated后,completion传值给上一个父视图方法
- #pragma pack(push,1)的一个副作用
- 设计模式之命令模式
- java 队列知识整理