您的位置:首页 > 其它

51nod 1572 宝岛地图 (预处理四个方向的最大步数优化时间,时间复杂度O(n*m+k))

2017-11-22 23:19 513 查看
题目:



这题如果没有时间限制的话暴力可以解,暴力的话时间复杂度大概是O(k*n),1s的话非常悬。

所以我们需要换个思路,我们对每个点预处理四个方向最多能走的步数,这个预处理时间复杂度是O(n*m)。

然后对每个字母点模拟一下即可。总时间复杂度O(n*m+k)。不会超时。

提示:没有满足要求的点时,要输出”no solution”,我就在这个上面WA了一次,不然应该可以一次AC的。

代码:

#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <vector>
#include <map>
#include <set>
#include <list>
#include <queue>
using namespace std;
typedef long long ll;
#define INF 2147483647

// 上N,下S,右E,左W。

//输入
int n,m,k;
char a[1010][1010];
struct node1{
int dir;int len;
}t[100010];

//b[i][j][k]表示点(i,j)往方向k最多可以走的步数。
int b[1010][1010][4];

//字母点
struct node{
int x;int y;char g;
bool operator<(node b)
{
return g < b.g;
}
};
list <node> l;
list <node>::iterator it;

int d[4][2] = {-1,0,1,0,0,1,0,-1};

//模拟q这个点走的过程
bool can(node q) {
int x = q.x;int y = q.y;
for(int i = 0;i < k; i++){
node1 s = t[i];
if(b[x][y][s.dir] < s.len) return false;
x = x + d[s.dir][0]*s.len;
y = y + d[s.dir][1]*s.len;
}
return true;
}

int main(){
//输入数据
cin >> n >> m;
node e;
for(int i = 1;i <= n; i++) {
for(int j = 1;j <= m; j++) {
cin >> a[i][j];
if(a[i][j] != '#' && a[i][j] != '.'){
e.x = i; e.y = j; e.g = a[i][j];
l.push_back(e);
}
}
}
//对子母点按字典序排序
l.sort();

for(int j = 1;j <= m; j++){
//预处理每个点最多能往北边走多少步
int num = 0;
for(int i = 1;i <= n; i++){
if(a[i][j] != '#'){
b[i][j][0] = num;num++;
}else{
num = 0;
}
}
//预处理每个点最多能往南边走多少步
num = 0;
for(int i = n; i >= 1; i--){
if(a[i][j] != '#'){
b[i][j][1] = num; num++;
}else{
num = 0;
}
}
}

for(int i = 1; i <= n; i++){
//预处理每个点最多能往东边走多少步
int num = 0;
for(int j = 1;j <= m; j++){
if(a[i][j] != '#'){
b[i][j][3] = num; num++;
}else{
num = 0;
}
}
//预处理每个点最多能往西边走多少步
num = 0;
for(int j = m; j >= 1; j--){
if(a[i][j] != '#'){
b[i][j][2] = num; num++;
}else{
num = 0;
}
}
}

//把字母方向转换成数字表示
cin >> k;
char key;
for(int i = 0;i < k; i++){
cin >> key >> t[i].len;
if(key == 'N') t[i].dir = 0;
else if(key == 'S') t[i].dir = 1;
else if(key == 'E') t[i].dir = 2;
else if(key == 'W') t[i].dir = 3;
}

//对每个子母点进行模拟
bool flag = false;
for(it = l.begin();it != l.end(); it++){
node q = *it;
if(can(q)){
cout << q.g;
flag = true;
}
}
if(!flag) cout << "no solution";
cout << endl;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: