[WITACM选拔赛]B题和C题最短路前缀和+二分
Posted cls1277
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[WITACM选拔赛]B题和C题最短路前缀和+二分相关的知识,希望对你有一定的参考价值。
Pro
比赛是在牛客上训练的时候打的重现赛
Sol
训练时:为什么就是做不对呢?我感觉思路没问题啊!
结束后:为什么一直错呢?明明思路都一模一样!
找到错后:woc!!!
B题:写了个bfs发现思路有大问题,因为bfs如果求最短路的话一定是第一个访问到的,但是本题第一个访问到的不一定最优。(写到这,突然想到一些东西,应该说朴素的bfs不可以,但是加上优先队列不知道可不可呢?)
B题正解:直接对每个点和周围的点连边,在传送门的两端连边(注意判断是否为陷阱),跑一遍最短路(dij堆优化模板)就好。
我错在哪了?因为是二维去转化成点的编号,应该是行号乘列数加列号!
C题:思路很简单,看到基本就想到了前缀和和二分,但是!就是WA(我太菜了
我错在哪了?首先w0一定是0,其实是一个n+1长度的数组,误以为n。发现这个错误后其实还没意识到排序的时候也是按照n个来排序的,所以继续在WA。事实上,只需要知道是n+1,然后把该改的地方改了就A了。
Code
B题
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<vector>
#include<map>
#include<stack>
using namespace std;
typedef long long LL;
#define PI acos(-1)
#define INF 2147483647
#define eps 1e-7
#define Fo(i,a,b) for(LL i=(a); i<=(b); i++)
#define Ro(i,b,a) for(LL i=(b); i>=(a); i--)
#define Ms(a,b) memset((a),(b),sizeof(a))
#define lowbit(_) _&(-_)
inline LL read() {
LL x = 0, f = 1;char c = getchar();
while (!isdigit(c)) { if (c == '-')f = -f;c = getchar(); }
while (isdigit(c)) x = (x << 1) + (x << 3) + (c ^ 48ll), c = getchar();
return x * f;
}
#define MAXN 90005
struct Node {
LL to , next , val;
};
Node e[MAXN*4+1005];
struct Seg {
LL x , y;
Seg() {
x=-1 , y=-1;
};
Seg(LL xx , LL yy) {
x=xx , y=yy;
}
};
vector<Seg>cq[305][305];
struct Que {
LL len , num;
Que(LL ll , LL nn) {
len = ll , num = nn;
}
};
LL tot , head[MAXN] , n , m , q , sx=-1 , sy=-1 , tx=-1 , ty=-1 , dis[MAXN];
string mp[305];
void add(LL x , LL y , LL z) {
tot++;
e[tot].to = y;
e[tot].next = head[x];
e[tot].val = z;
head[x] = tot;
}
bool operator < (Que a , Que b) {
return a.len > b.len;
}
void dij(LL s) {
Fo(i,0,MAXN)
dis[i] = INF;
dis[s] = 0;
priority_queue<Que>q;
q.push(Que(0,s));
while(!q.empty()) {
Que u=q.top();
q.pop();
if(u.len!=dis[u.num]) continue;
for(int i=head[u.num]; i;i=e[i].next) {
LL v=e[i].to;
if(dis[v]>dis[u.num]+e[i].val) {
dis[v] = dis[u.num]+e[i].val;
q.push(Que(dis[v] , v));
}
}
}
}
int main() {
// freopen("datad.txt","r",stdin);
n=read(); m=read(); q=read();
Fo(i,0,n-1) cin>>mp[i];
Fo(i,1,q) {
LL x1 , z1 , x2 , z2;
// x1=read(); z1=read(); x2=read(); z2=read();
scanf("%lld%lld%lld%lld",&x1,&z1,&x2,&z2);
cq[x1][z1].push_back(Seg(x2,z2));
cq[x2][z2].push_back(Seg(x1,z1));
}
Fo(i,0,n-1) {
Fo(j,0,m-1) {
if(mp[i][j]=='#') continue;
if(mp[i][j]=='S') {
sx = i , sy = j;
}
if(mp[i][j]=='T') {
tx = i , ty = j;
}
if(i-1>=0&&mp[i-1][j]!='#')
add(i*m+j , (i-1)*m+j , 1);
if(i+1<n&&mp[i+1][j]!='#')
add(i*m+j , (i+1)*m+j , 1);
if(j-1>=0&&mp[i][j-1]!='#')
add(i*m+j , i*m+j-1 , 1);
if(j+1<m&&mp[i][j+1]!='#')
add(i*m+j , i*m+j+1 , 1);
if(cq[i][j].size()!=0)
Fo(k,0,cq[i][j].size()-1)
if(mp[cq[i][j][k].x][cq[i][j][k].y]!='#')
add(i*m+j , cq[i][j][k].x*m+cq[i][j][k].y , 3);
}
}
if((sx==-1&&sy==-1)&&(tx==-1&&ty==-1)) {
printf("0");
return 0;
}
if((sx==-1&&sy==-1)||(tx==-1&&ty==-1)) {
printf("-1");
return 0;
}
dij(sx*m+sy);
if(dis[tx*m+ty]==INF)
printf("-1");
else
printf("%lld",dis[tx*m+ty]);
return 0;
}
C题
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<vector>
#include<map>
#include<stack>
using namespace std;
typedef long long LL;
#define PI acos(-1)
#define INF 2147483647
#define eps 1e-7
#define Fo(i,a,b) for(LL i=(a); i<=(b); i++)
#define Ro(i,b,a) for(LL i=(b); i>=(a); i--)
#define Ms(a,b) memset((a),(b),sizeof(a))
#define lowbit(_) _&(-_)
inline LL read() {
LL x = 0, f = 1;char c = getchar();
while (!isdigit(c)) { if (c == '-')f = -f;c = getchar(); }
while (isdigit(c)) x = (x << 1) + (x << 3) + (c ^ 48ll), c = getchar();
return x * f;
}
#define MAXN 100005
struct Node {
LL data , id;
Node(){};
Node(LL dd , LL ii) {
data = dd , id = ii;
}
bool operator < (const Node &a) {
return data<a.data;
}
};
Node a[MAXN];
LL n , m , tt[MAXN] , ans;
struct cmp {
bool operator() (const Node& s1, const Node& s2) {
return s1.data<s2.data;
}
};
int main() {
// freopen("data.txt","r",stdin);
n=read(); m=read();
a[0].id = a[0].data = 0;
Fo(i,1,n) {
LL x = read();
a[i].data = a[i-1].data + x;
a[i].id = i;
}
sort(a , a+n+1);
Fo(i,0,n)
tt[i] = a[i].data;
Fo(i,1,m) {
LL k=read();
LL pos = upper_bound(tt , tt+n+1 , k)-tt-1;
LL sum = k-tt[pos];
ans = a[pos].id;
Ro(j,pos-1,0) {
if(k-tt[j]!=sum)
break;
ans = max(ans , a[j].id);
}
printf("%lld\\n",ans);
}
return 0;
}
以上是关于[WITACM选拔赛]B题和C题最短路前缀和+二分的主要内容,如果未能解决你的问题,请参考以下文章