一次非常神奇的考试,考完试以后看着T2的0pts突然笑死我自己
太智障了这什么神奇的题意理解错误23333
T1一眼分类讨论,两眼二分,觉得分类讨论有点玄学但是出题人八成不会卡【何】,然后本着对二分的恐惧打了玄学
关于T2,我没了 豹笑 我没想到一只鸟可能被打两枪你敢信
T3?今天有T3?
T1:
正解是显而易见的二分。然而我比较懒,又经常在二分上炸掉【写得比较丑】,而且第一眼其实并不是二分。
如果k最后小于1,那么相对于原来1个单位时间的移动来说,肯定这种上下移动的步数越多越好。先dfs一次,跑出从起点到终点上下移动步数最多的最短路,然后计算出对应的k。如果这个k解出来大于1,就再跑一次使左右移动步数最多的最短路,再次解出k。这样可以保证选取这个k的同时,跑的一定是最短路。
其实总是隐约不太放心,感觉可能有锅XD然而最后A了
#include<iostream> #include<cstdio> #include<queue> #include<cstring> using namespace std; int n,m,sx,sy,tx,ty; int a[110][110],vis[110][110]; int h[4]={0,-1,0,1}; int l[4]={-1,0,1,0}; double s; struct node{ int x,y,tmp,dis; bool operator < (const node a) const { return tmp < a.tmp; } }; priority_queue<pair<int,node> >q; node dfs1(){ node u; u.x=sx,u.y=sy,u.tmp=0; q.push(make_pair(0,u)); while(!q.empty()){ while(q.size()&&vis[q.top().second.x][q.top().second.y])q.pop(); if(!q.size())break; int d=-q.top().first; node x=q.top().second; q.pop(); vis[x.x][x.y]=1; if(x.x==tx&&x.y==ty){ x.dis=d; return x; } for(int i=0;i<4;i++){ node y=x; y.x+=h[i],y.y+=l[i]; if(y.x>0&&y.x<=n&&y.y>0&&y.y<=m&&!a[y.x][y.y]){ if(i==1||i==3)y.tmp++; q.push(make_pair(-(d+1),y)); } } } } node dfs2(){ node u; u.x=sx,u.y=sy,u.tmp=0; while(!q.empty())q.pop(); memset(vis,0,sizeof(vis)); q.push(make_pair(0,u)); while(!q.empty()){ while(q.size()&&vis[q.top().second.x][q.top().second.y])q.pop(); if(!q.size())break; int d=-q.top().first; node x=q.top().second; q.pop(); vis[x.x][x.y]=1; if(x.x==tx&&x.y==ty){ x.dis=d; return x; } for(int i=0;i<4;i++){ node y=x; y.x+=h[i],y.y+=l[i]; if(y.x>0&&y.x<=n&&y.y>0&&y.y<=m&&!a[y.x][y.y]){ if(i==0||i==2)y.tmp++; q.push(make_pair(-(d+1),y)); } } } } int main() { scanf("%d%d",&n,&m); scanf("%d%d%d%d",&sx,&sy,&tx,&ty); for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ scanf("%d",&a[i][j]); } } scanf("%lf",&s); node b=dfs1(); double k=(1.0*s-1.0*b.dis+1.0*b.tmp)/(1.0*b.tmp);//tmp上下,dis-tmp左右 if(k<1)printf("%.3lf",k); else{ b=dfs2(); k=(1.0*s-1.0*b.tmp)/(1.0*(b.dis-b.tmp));//tmp左右,dis-tmp上下 printf("%.3lf",k); } return 0; }