7.5 The Morning after Halloween
本题主要是存储的问题,在存储上笔者原先的代码占用了大量的内存空间
这边笔者采用暴力的思想直接硬开所有情况的16^6的数组来存储该问题,当然这在时间上是十分浪费的,因为初始化实在太慢了,剩下的就是状态转移,以及隐式图的相关思路
点击查看笔者代码
#include<iostream>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
constexpr int maxl = 16, maxn = 16777216+5, base = 4, debase = 15;
int w, h, n, des, sta, st[maxl/4][2], ed[maxl/4][2], G[maxl][maxl];
int dx[5] = {0, 0, 0, 1, -1};
int dy[5] = {0, 1, -1, 0, 0};
bool vis[maxn];
struct Node{
int value, costed;
Node(int value = 0, int costed = 0) : value(value), costed(costed) {}
};
bool getD() {
cin >> w >> h >> n;
if(!w) return false;
int cnt = 0, buf[26][2][2], sign[26]; memset(sign, 0, sizeof(sign));
string line; getline(cin, line); memset(G, 1, sizeof(G));
for(int i = 0; i < h; i++) {
getline(cin, line);
int len = line.length();
for(int j = 0; j < len; j++) {
if(line[j] == ' ') G[i][j] = 1;
else if(line[j] == '#') G[i][j] = 0;
else {
G[i][j] = 1;
if(isupper(line[j])) { buf[line[j]-'A'][0][0] = i; buf[line[j]-'A'][0][1] = j; sign[line[j]-'A'] = 1; }
else { buf[line[j]-'a'][1][0] = i; buf[line[j]-'a'][1][1] = j; sign[line[j]-'a'] = 1; }
}
}
}
memset(vis, 0, sizeof(vis));
for(int i = 0; i < 26; i++)
if(sign[i]) {
st[cnt][0] = buf[i][1][0]; st[cnt][1] = buf[i][1][1];
ed[cnt][0] = buf[i][0][0]; ed[cnt++][1] = buf[i][0][1];
}
return true;
}
int toInt(int (&arr)[4][2]) {
int temp = 0;
for(int i = 0; i < n; i++) {
temp = (((temp<<4)|arr[i][0]) << 4) | arr[i][1];
}
return temp;
}
#ifdef LOCAL
#include<algorithm>
void output(int num) {
string line;
do {
line += num%2+'0';
num /= 2;
} while(num);
reverse(line.begin(), line.end());
cout << line << endl;
}
#endif
void output(int (&arr)[4][2]) {
for(int i = 0; i < n; i++) cout << arr[i][0] << " " << arr[i][1] << " ";
cout << endl;
}
void toPos(int num, int (&arr)[4][2]) {
for(int i = n-1; i >= 0; i--) {
arr[i][1] = num & debase;
num = num >> base;
arr[i][0] = num & debase;
num = num >> base;
}
}
void findPath(vector<int> &v, int cur, int (&npos)[4][2], int (&pos)[4][2]) {
if(cur == n) {
for(int i = 0; i < n; i++)
for(int j = i+1; j < n; j++)
if((npos[i][0] == npos[j][0] && npos[i][1] == npos[j][1]) || (npos[i][0]==pos[j][0] && npos[i][1]==pos[j][1] && npos[j][0]==pos[i][0] && npos[j][1]==pos[i][1])) return;
int temp = toInt(npos);
if(!vis[temp]) {
vis[temp] = true;
v.push_back(temp);
}
return;
}
for(int i = 0; i < 5; i++) {
int nx = pos[cur][0] + dx[i], ny = pos[cur][1] + dy[i];
if(nx >= 0 && nx < h && ny >= 0 && ny < w && G[nx][ny]) {
npos[cur][0] = nx; npos[cur][1] = ny;
findPath(v, cur+1, npos, pos);
}
}
}
int main() {
while(getD()) {
sta = toInt(st);
des = toInt(ed);
queue<Node> q;
q.push(Node(sta, 0));
int ans = 0;
vis[sta] = true;
while(!q.empty()) {
Node temp = q.front(); q.pop();
if(temp.value == des) { ans = temp.costed; break; }
int pos[4][2], npos[4][2];
toPos(temp.value, pos);
vector<int> v;
findPath(v, 0, npos, pos);
for(int i = 0; i < v.size(); i++) q.push(Node(v[i], temp.costed+1));
}
cout << ans << endl;
}
return 0;
}
注意,对于这种转移代价高的,我们要想办法减少转移代价,因为其实题目中有很多障碍格,因此并不是所有四个方向都能移动,因此可以把所有空格提出来建立一张图,而不是每次临时判断5中方法是否合法
其次,是换一个算法,例如双向广度优先搜索,双向BFS首先需要直到起点和终点,然后就可以正着搜索一层,反着搜索一层,这样交替下去,直到两层中出现相同的状态
A算法也是挺好的,不过此时就是使用优先队列,A算法最重要的就是估值函数的选取,
f(x) = h(x) + g(x)
h(x):是当前到x所需要花费的代价
g(x):启发式信息,根据x推断到达终点所需要花费的代价,一个好的启发式算法可以大大减少需要搜索遍历到的点
7.5 The Morning after Halloween的更多相关文章
- POJ 3370. Halloween treats 抽屉原理 / 鸽巢原理
Halloween treats Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 7644 Accepted: 2798 ...
- Lightoj 题目1422 - Halloween Costumes(区间DP)
1422 - Halloween Costumes PDF (English) Statistics Forum Time Limit: 2 second(s) Memory Limit: 32 ...
- CSUFT 1004 This is Halloween: Saving Money
1004: This is Halloween: Saving Money Time Limit: 1 Sec Memory Limit: 128 MB Submit: 11 So ...
- [POJ 3370] Halloween treats
Halloween treats Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 7143 Accepted: 2641 ...
- poj 3370 Halloween treats(鸽巢原理)
Description Every year there is the same problem at Halloween: Each neighbour is only willing to giv ...
- LightOJ - 1422 Halloween Costumes (区间dp)
Description Gappu has a very busy weekend ahead of him. Because, next weekend is Halloween, and he i ...
- UVA 11237 - Halloween treats(鸽笼原理)
11237 - Halloween treats option=com_onlinejudge&Itemid=8&page=show_problem&category=516& ...
- 鸽巢原理应用-分糖果 POJ 3370 Halloween treats
基本原理:n+1只鸽子飞回n个鸽笼至少有一个鸽笼含有不少于2只的鸽子. 很简单,应用却也很多,很巧妙,看例题: Description Every year there is the same pro ...
- UVA1601-The Morning after Halloween(双向BFS)
Problem UVA1601-The Morning after Halloween Accept: 289 Submit: 3136 Time Limit: 12000 mSec Problem ...
- [uva P1601] The Morning after Halloween
[uva P1601] The Morning after Halloween 题目链接 非常经典的一道题目,lrj的书上也有(貌似是紫书?). 其实这题看起来就比较麻烦.. 首先要保证小鬼不能相遇, ...
随机推荐
- 1 Mybatis动态SQL
Mybatis动态SQL 1. 注解开发 我们也可以使用注解的形式来进行开发,用注解来替换掉xml. 使用注解来映射简单语句会使代码显得更加简洁,但对于稍微复杂一点的语句,Java 注解不仅力不从 ...
- Python-100-Days-master
跟着python100学习一下 100以内的素数 # 输出100以内的所有素数 # 想法:从1到100遍历,假设得到了i=17,那么此时从1到9遍历,如果找到了一个数用17能除尽则跳出循环 # 如果找 ...
- 基于SqlSugar的开发框架循序渐进介绍(3)-- 实现代码生成工具Database2Sharp的整合开发
我喜欢在一个项目开发模式成熟的时候,使用代码生成工具Database2Sharp来配套相关的代码生成,对于我介绍的基于SqlSugar的开发框架,从整体架构确定下来后,我就着手为它们量身定做相关的代码 ...
- JavaMetaweblogClient,Metaweblog的java实现-从此上传博客实现全平台
目录 1. 什么是Metaweblog? 2. Metaweblog的应用 3. 如何使用Metaweblog 4. 本项目介绍 4.1 metaweblog与java之间的关系映射 4.2 使用Ja ...
- Unity实现”对象池管理器“
前言:警告!这可能是坨屎,空闲时间写成,仅作娱乐 在Unity中生成或销毁一个物体会占用较大的资源,如果是制作FPS射击游戏,子弹生成更是雪上加霜.所以我自己写了一个PoolManager,不能和网上 ...
- Python Django 功能模块
Python Django模块 Django模块,是针对有django基础,对django功能进行模块化,方便下次使用. 一.注册模块 该注册采用邮箱验证,注册成功后会发送激活链接到邮箱. 邮箱验证参 ...
- 制造企业信息化时代,SaaS系统下沉,移动端上升
这个时代,我们是不是有很多岗位一定是要在电脑前面完成?如果我们让部分岗位的办公室人员离开电脑,让他们通过移动端来完成工作,这又会产生出一个什么样的变化?是否意味着可以有更多的时间在一线生产制造现场,从 ...
- 用Arduino显示颜色序列(u8g2,OLED)
目录 用Arduino显示颜色序列(u8g2,OLED) 用Arduino显示颜色序列(u8g2,OLED) 提前祝大家新年快乐! 主控:Arduino Mega 2560 硬件:126×64 OLE ...
- 《HALCON数字图像处理》第四章笔记
目录 第四章 HALCON数据结构 HALCON Image图像 图像通道 HALCON Region区域 Region的初步介绍 Region的点与线 Region的行程 Region的区域特征 H ...
- 国内外组态软件对比分析(InTouch、WinCC、iFix、iNeuOS)
在我国自动化控制领域应用较广泛的工业自动化组态软件有Wonderware公司InTouch.西门子公司Wincc.GE公司iFix.国内也有一些传统组态软件厂商,使用的功能和形式基本上十分类似,受当时 ...