换队长来写,估计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->Y
std::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 debug
if (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 me!
//更新说明:
//修改了类的定义方式,在定义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);
else fill(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;
}