能解决一个判定可视范围的code,SLAM相关

来源:互联网 发布:http jd2017b.123js 编辑:程序博客网 时间:2024/06/12 21:16

换队长来写,估计20min解决。

而我写了8个小时QAQ


#include <bits/stdc++.h>using std::cin;using std::endl;using std::cout;struct pix{int x, y;pix(){}pix(int a,int b):x(a),y(b){}};std::ostream& operator << (std::ostream &f, pix a){f<<"("<<a.x<<","<<a.y<<")";return f;}int operator == (pix A, pix B){return (A.x == B.x && A.y == B.y);}inline int isRightHand(pix A, pix B){//返回大于0的数字,则满足A是B的右手螺旋方向//0表示2向量共线//小于0,则B是A的右手螺旋方向 return B.y*A.x - A.y*B.x;}class solve{private:int X, Y;//col-> X   row->Ystd::vector<std::vector<int> > map;std::vector<std::vector<int> > vis;std::vector<std::vector<int> > cho;//选中状态public:void init(const std::string &filename){std::ifstream ifs;ifs.open(filename.c_str());ifs >> X >> Y;map.clear();map.resize(X);for (int i = 0; i < X; ++ i){map[i].resize(Y);for (int j = 0; j < Y; ++ j){ifs >> map[i][j];}}for (int i = 0; i < X; ++ i){map[i][0] = map[i][Y-1] = 1;}for (int i = 0; i < Y; ++ i){map[0][i] = map[X - 1][i] = 1;}ifs.close();cho = vis = map;}void fill(int nx, int ny, int dx, int end, int flag ,int dy=0x7ffffff){if (dy != 0x7ffffff){//此为竖着画for (int i = ny; i != end; i += dy){/*if (vis[nx][i] != 0)//这一竖排已经填过了{break;}*/if (map[nx][i] == 1 && flag == 1){fill(nx, i, dx, end, -1, dy);break;}vis[nx][i] = flag;}}else{for (int i = nx; i != end; i += dx){if (vis[i][ny] != 0)//这行已经填好了{break;}if (map[i][ny] == 1 && flag == 1){fill(i, ny, dx, end, -1);break;}vis[i][ny] = flag;}}}int centerx, centery;//循环模拟递归int flag=0;void update(int nx, int ny, int dx, int dy, int endx, int endy){//#define debugif (flag) {cout<<"    开始处理("<<nx<<","<<ny<<")"<<endl;}int y = ny;double k = (double)(nx-centerx) / (double)(ny-centery);for (; ; y -= dy){int x;if (dx > 0){x = std::ceil(k * ((y - centery)- 0.5 * dy)) + centerx;}else{x = std::floor(k * ((y - centery)- 0.5 * dy)) + centerx;}if (flag){printf("在%d行,是第%d个元素开始有光通过  ", y, x);printf("上一行是第%d行,第%d个元素,这个元素的取值为%d\n",y-dy, x-dx, vis[x-dx][y-dy]);}if (vis[x - dx][y - dy] == 1){//下一层光是通的break;}if (vis[x - dx][y - dy] == -1){//下一层光不通break;}//下一层未知,则继续}for (; y != ny + dy ;y += dy){int x;if (dx > 0){x = std::ceil(k * ((y - centery)- 0.5 * dy)) + centerx;}else{x = std::floor(k * ((y - centery)- 0.5 * dy)) + centerx;}/*if (flag){cout << x<<" "<<y<<" !"<<endl;cout<< vis[x-dx][y-dy]<<endl;}*/if (vis[x - dx][y - dy] == -1 || vis[x][y - dy] == -1){//如果上一个节点光路不通,那么这一行肯定光路也都不通fill(x, y, dx, endx, -1);continue;}//if (flag)cout<<x<<" "<<y<<"@@@"<<endl;//剩下的情况,就是光路通的情况fill(x, y, dx, endx, 1);}}void pg(){for (int i = 0; i < X; ++ i){for (int j = 0; j < Y; ++ j){printf("%d\t", vis[i][j]);//cout << vis[i][j]<<" ";}cout << endl;}}void output(){for (int i = 0; i < X; ++ i){for (int j = 0; j < Y; ++ j){printf("%d\t", vis[i][j]==-1?0:1);//cout << vis[i][j]<<" ";}cout << endl;}}void core(){//vis[i][j] 为0,则该点状态未知,1为可行。 -1为不可达centerx = X / 2;centery = Y / 2;//cout<<X<<" "<<Y<<endl;for (int i = 0; i < X; ++ i){for (int j = 0; j < Y; ++ j){vis[i][j] =0;}}vis[centerx][centery] = 1;fill(centerx +1, centery, 1, X, 1);fill(centerx -1, centery, -1, -1, 1);//第一象限for (int y = centery +1; y != Y; ++ y){update(X -1, y, 1, 1, X ,Y);}for (int x = X - 2; x > centerx; -- x){update(x, Y - 1, 1, 1, X ,Y);}//第二象限for (int y = centery + 1; y != Y; ++ y){update(0, y, -1, 1, -1, Y);}//flag = 1;for (int x = 1; x != centerx; ++ x){update(x, Y - 1, -1, 1, -1, Y);//pg();}//flag = 0;//exit(0);//第三象限for (int y = centery -1; y >= 0; -- y){update(0, y, -1, -1, -1, -1);}for (int x = 0; x < centerx; ++ x){update(x, 0, -1, -1, -1, -1);}//第四象限for (int y = centery -1; y >=0; -- y){update(X-1, y, 1, -1, X, -1);}for (int x = X -1; x > centerx; -- x){update(x, 0, 1, -1, X, -1);}fill(centerx, centery - 1, 0, -1, 1, -1);fill(centerx, centery + 1, 0, Y ,1, 1); for (int x = 0; x < X;++x)for (int y = 0; y < Y; ++ y)if (vis[x][y]==0){cout<<x<<" "<<y<<endl;exit(0);}}};int main(){solve x;x.init("data.txt");x.core();x.output();return 0;}/*   10 10   1 1 1 1 1 1 1 1 1 1   1 0 0 0 0 1 1 0 1 1   1 1 0 1 1 1 1 0 0 1   1 0 0 0 0 0 0 0 0 1   1 1 0 0 0 0 0 0 0 1   1 1 1 0 0 0 0 0 0 1   1 1 0 0 0 0 0 0 0 1   1 1 0 0 0 0 0 1 0 1   1 1 1 1 0 0 0 0 0 1   1 1 1 1 1 1 1 1 1 1   */


然后速度提升70%后的程序

//2017-10-15 21:31:37//by Xue Bohuan//bohuan.xue@gmail.com / calebxue@qq.com//更新说明://修改了类的定义方式,在定义solve的同时指定地图大小。//取消了vector设定,预处理了double计算,优化了常数//最终完成样例png大致计算所用时间大约5-10 ms//可以考虑的优化方案:在预处理除法的同时考虑象限变换,利用对称性减少除法次数。#include <bits/stdc++.h>using std::cin;using std::endl;using std::cout;/* * 直接调用init data * data第一行n m表示下面数据有n行,m列 * 接着有n行,每行m个数字。每个数字非0即1! * 1表示有障碍。 * 调用完init后,调用run函数。接着output则为输出整个图片(n行m列,每个数字非0即1) * */template<int size_X, int size_Y> //地图的高!和宽!!class solve{private:int X, Y;bool map[size_X][size_Y];int vis[size_X][size_Y];double kk[size_X][size_Y];int centerx, centery;public:int debug;double st;void thickenWall(int nx, int ny, int dx, int dy, int endx, int endy){memset(vis, 0, sizeof(vis));for (int x = nx; x != endx - dx; x += dx)for (int y = ny; y != endy; y += dy){if (map[x][y] == 0)continue;if (map[x+dx][y-dy])vis[x][y] = 1;}for (int x = nx; x != endx; x += dx)for (int y = ny ; y != endy; y += dy)if (vis[x][y])map[x + dx][y] = 1;}void init(const std::string &filename){std::ifstream ifs;ifs.open(filename.c_str());debug=0;ifs >> X >> Y;centerx = X / 2;centery = Y / 2;for (int i = 0; i < X; ++ i){for (int j = 0; j < Y; ++ j){ifs >> map[i][j];kk[i][j] = (double)(i - centerx) / (double)(j - centery);}}st=clock();thickenWall(centerx + 1, centery + 1,  1,  1,  X,  Y);thickenWall(centerx - 1, centery + 1, -1,  1, -1,  Y);thickenWall(centerx - 1, centery - 1, -1, -1, -1, -1);thickenWall(centerx + 1, centery - 1,  1, -1,  X, -1);for (int i = 0; i < X; ++ i)map[i][0] = map[i][Y-1] = true;for (int i = 0; i < Y; ++ i)map[0][i] = map[X - 1][i] = true;ifs.close();}void fill(const int &nx, const int &ny, const int &dx, int end, int flag ,int dy=0x7ffffff){if (dy != 0x7ffffff){for (int i = ny; i != end; i += dy){if (map[nx][i] && flag == 1){fill(nx, i, dx, end, -1, dy);break;}vis[nx][i] = flag;}}else{if (nx == centerx)fill(nx + dx, ny, dx, end, flag);for (int i = nx; i != end; i += dx){if (vis[i][ny] != 0)break;if (map[i][ny] && flag == 1){fill(i, ny, dx, end, -1);break;}vis[i][ny] = flag;}}}int getxxx(int &x, int &xxx, const double &k, const int &y, const int &dy, const int &dx){if (dx > 0){x   = std::ceil(k * ((y - centery ) - 0.5 * dy)) + centerx;int tmp = std::floor(k * ((y - centery) + 0.5 * dy)) + centerx;if (x > tmp) x = std::move(tmp);xxx = std::floor(k * ((y - centery -dy) + 0.5 * dy)) + centerx; }else{x   = std::floor(k * ((y - centery ) - 0.5 * dy)) + centerx;int tmp = std::ceil(k * ((y - centery ) + 0.5 * dy)) + centerx;if (x < tmp)x= std::move(tmp);xxx = std::ceil(k * ((y - centery -dy) + 0.5 * dy)) + centerx;}return vis[xxx][y-dy];}void update(int nx, int ny, int dx, int dy, int endx, int endy){int y = ny, x, xxx;double k = kk[nx][ny];//(double)(nx-centerx) / (double)(ny-centery);for (; !getxxx(x, xxx, k, y, dy, dx); y -= dy);for (; y != ny + dy ;y += dy){getxxx(x, xxx, k, y, dy, dx);if (vis[xxx][y - dy] == -1 )fill(x, y, dx, endx, -1);elsefill(x, y, dx, endx, 1);}}void output(){for (int i = 0; i < X; ++ i){for (int j = 0; j < Y; ++ j)printf("%d\t", vis[i][j]==-1?0:1);printf("\n");}}void core(){memset(vis, 0, sizeof(vis));vis[centerx][centery] = 1;fill(centerx +1, centery, 1, X, 1);fill(centerx -1, centery, -1, -1, 1);for (int y = centery +1; y != Y; ++ y)update(X -1, y, 1, 1, X ,Y);for (int x = X - 2; x > centerx; -- x)update(x, Y - 1, 1, 1, X ,Y);fill(centerx, centery + 1, 0, Y ,0, 1);for (int y = centery + 1; y != Y; ++ y)update(0, y, -1, 1, -1, Y);for (int x = 1; x != centerx; ++ x)update(x, Y - 1, -1, 1, -1, Y);for (int y = centery -1; y >= 0; -- y)update(0, y, -1, -1, -1, -1);for (int x = 0; x < centerx; ++ x)update(x, 0, -1, -1, -1, -1);fill(centerx, centery - 1, 0, -1, 0, -1);for (int y = centery -1; y >=0; -- y)update(X-1, y, 1, -1, X, -1);for (int x = X -1; x > centerx; -- x)update(x, 0, 1, -1, X, -1);fill(centerx, centery - 1, 0, -1, 1, -1);fill(centerx, centery + 1, 0, Y ,1, 1);for (int x = 0; x < X;++x)for (int y = 0; y < Y; ++ y)assert(vis[x][y]);}};solve<500,400> x;int main(){x.init("data.txt");x.core();//cout<<"程序计算时间为(不算输出和读入时间)";//cout<< (clock()-x.st)/ CLOCKS_PER_SEC << " 秒"<<endl;//return 0;if (!x.debug)x.output();return 0;}


阅读全文
0 0