[codeforces 1296C] Yet Another Walking Robot 三重排序+全网唯一的代码/STL中map+pair/类hash算法
总目录详见https://blog.csdn.net/mrcrack/article/details/103564004
在线测评地址https://codeforces.com/contest/1296/problem/C
方法一:三重排序+全网唯一的代码
Problem | Lang | Verdict | Time | Memory |
---|---|---|---|---|
C - Yet Another Walking Robot | GNU C++11 | Accepted | 46 ms | 2400 KB |
//找环
/*
This optimization is a low-budget project so you need to remove the shortest possible non-empty substring to optimize the robot's path such that the endpoint of his path doesn't change.
上句中的he shortest possible non-empty substring尤为关键,删除最短的。
英文实力还需加强。
*/
#include <cstdio>
#include <algorithm>
#define maxn 200010
using namespace std;
struct node{
int seq,x,y;//seq访问顺序;x,y坐标
}p[maxn];
char s[maxn];
int cmp(node a,node b){//三重排序
return a.x==b.x?(a.y==b.y?a.seq<b.seq:a.y<b.y):a.x<b.x;
}
int main(){
int t,n,l,r,i;
scanf("%d",&t);
while(t--){
scanf("%d%s",&n,s+1);
p[0].seq=0,p[0].x=0,p[0].y=0,l=0,r=n;//初始化
for(i=1;i<=n;i++)
if(s[i]=='L')p[i].seq=i,p[i].x=p[i-1].x-1,p[i].y=p[i-1].y;
else if(s[i]=='R')p[i].seq=i,p[i].x=p[i-1].x+1,p[i].y=p[i-1].y;
else if(s[i]=='U')p[i].seq=i,p[i].x=p[i-1].x,p[i].y=p[i-1].y+1;
else if(s[i]=='D')p[i].seq=i,p[i].x=p[i-1].x,p[i].y=p[i-1].y-1;
sort(p+0,p+n+1,cmp);//范了一个很大的错误,此处错写成sort(p+0,p+0+n,cmp);查了1个小时,请注意sort是左闭右开函数.
for(i=1;i<=n;i++){
if(p[i].x==p[i-1].x&&p[i].y==p[i-1].y)//起点终点是同一个点
if(p[i].seq-(p[i-1].seq+1)<r-l)l=p[i-1].seq+1,r=p[i].seq;//取最小值
}
if(r-l==n)printf("-1\n");//数据一直未更新l=0,r=n
else printf("%d %d\n",l,r);
}
return 0;
}
方法二:STL中map+pair
Problem | Lang | Verdict | Time | Memory |
---|---|---|---|---|
C - Yet Another Walking Robot | GNU C++11 | Accepted | 46 ms | 8000 KB |
//STL中map+pair
思路同https://www.cnblogs.com/pixel-Teee/p/12272446.html
我们可以使用关联数组map,存储走过的路径的坐标到字符串下标的映射,我们只要走过的坐标点曾经出现过,说明我们走了一段徒劳的路径,那么我们就更新最小的区间的两端。
#include <cstdio>
#include <map>
using namespace std;
char s[200010];
map< pair<int,int>,int > mp;
pair<int,int> p;
int main(){
int t,n,i,l,r;
scanf("%d",&t);
while(t--){
scanf("%d%s",&n,s+1);
mp.clear();//别忘了初始化
p.first=0,p.second=0,mp[p]=0,l=0,r=n;
for(i=1;i<=n;i++){
if(s[i]=='L')--p.first;
else if(s[i]=='R')++p.first;
else if(s[i]=='U')++p.second;
else if(s[i]=='D')--p.second;
if(mp.count(p))//mp中已存p值为1,未存p值为0
if(i-(mp[p]+1)<r-l)l=mp[p]+1,r=i;//找最小值
mp[p]=i;
}
if(r-l==n)printf("-1\n");//n-0==n
else printf("%d %d\n",l,r);
}
return 0;
}
方法三:类hash算法
Problem | Lang | Verdict | Time | Memory |
---|---|---|---|---|
C - Yet Another Walking Robot | GNU C++11 | Accepted | 61 ms | 8100 KB |
//类hash算法
//想过但没有实现
//思路同https://blog.csdn.net/qq_37504214/article/details/104195791
/*
'L' -1;'R' +1;'U' +200007;'D' -200007
200007*200000=4*10^10 int溢出,需用long long
*/
//map查重真是个好帮手。
#include <cstdio>
#include <map>
#define L -1
#define R 1
#define U 200007
#define D -200007
#define LL long long
using namespace std;
char s[200010];
map<LL,int> mp;
int main(){
int t,i,n,l,r;
LL p;
scanf("%d",&t);
while(t--){
scanf("%d%s",&n,s+1);
mp.clear(),p=0,mp[0]=0,l=0,r=n;
for(i=1;i<=n;i++){
if(s[i]=='L')p+=L;
else if(s[i]=='R')p+=R;
else if(s[i]=='U')p+=U;
else if(s[i]=='D')p+=D;
if(mp.count(p))
if(i-(mp[p]+1)<r-l)l=mp[p]+1,r=i;
mp[p]=i;
}
if(r-l==n)printf("-1\n");
else printf("%d %d\n",l,r);
}
return 0;
}