B2. Koa and the Beach (Hard Version)
B1. Koa and the Beach (Easy Version)
题意
一个人从岸边位置0 游到 岛上位置n+1
中间n个水域的深度为d[i]
同时由于潮汐海水深度一直在周期的变化d[i]+p[tmod2k]
其中p=[0,1,2,…,k−2,k−1,k,k−1,k−2,…,2,1]
而这个人不能通过深度为L的水域 问最后这个人能否到达对岸
题解
easy version
可以将{位置,潮汐增加高度,是否处于涨潮期}这个状态视为一个结点
而当前结点是否能转移到其他结点x的条件是d[x]+潮汐增加高度<=l
于是将所有状态点构成一个图 进行dfs搜素是否能够到达n+1位置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| #include <bits/stdc++.h> using namespace std; typedef long long ll; #define endl '\n' #define Turnoff std::ios::sync_with_stdio(false) const ll Max=100+5; int deep[Max]; int n,k,l;bool ok; set<pair<int,pair<int,bool> > >vis;
void dfs(int pos,int tide,bool down){ if(pos>n){ ok=1; return; } if(vis.count({pos,{tide,down}}))return; else vis.insert({pos,{tide,down}}); tide+=(down?-1:1); if(tide==k||tide==0)down=!down; if(deep[pos+1]+tide<=l)dfs(pos+1,tide,down); if(deep[pos]+tide<=l)dfs(pos,tide,down); if(deep[pos]+tide<l&&deep[pos+1]+tide>l)return; } int main() { int t;cin>>t; while(t--){ ok=0;cin>>n>>k>>l; deep[0]=-k,deep[n+1]=-k; vis.clear(); for(int i=1;i<=n;i++)cin>>deep[i]; dfs(0,0,0); if(!ok)cout<<"No"<<endl; else cout<<"Yes"<<endl; } }
|
hard version
先找到所有安全的水域 safepos即无论何时 他都不会溺水deep[i]+k<=l
然后问题被分解成能否顺利从一个safepos到达下一个safepos
v形曲线表示落潮-涨潮
策略是当他处于某个安全水域时
在落潮到下个点的深度在下一秒刚好不溺水时假设为 t0 游到下一个点
然后反复使用这个策略到达下一个安全点最后t1时刻到达下一个安全点
或者说落潮时当下一个点恰好能安全通过时最快的通过它的策略能避免溺水
假设不是处于t0时游到下一个点 而时t0’
那么最早到达下一个安全点时为t1’
那么会比“在落潮到下个点的深度在下一秒刚好不溺水时”出发 在t1~t1’所在的水域会多出一些深度
当最优的策略也无法通过时就输出”NO”
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| #include <bits/stdc++.h> using namespace std; typedef long long ll; #define endl '\n' #define Turnoff std::ios::sync_with_stdio(false) const ll Max=3e5+5; ll deep[Max];
int main() { int t;cin>>t; while(t--){ ll n,k,l; cin>>n>>k>>l; vector<int>safe; for(int i=1;i<=n;i++){ cin>>deep[i]; if(deep[i]+k<=l)safe.push_back(i); } safe.push_back(n+1);deep[n+1]=-k; int now=0;bool flag=0; for(auto i:safe){ ll tide=min(k,l-deep[now+1]); if(tide<0)flag=1;bool down=1; while(now<i){ if(tide+deep[now+1]<=l)now++; else { ll ntide=min(k,l-deep[now+1]); if(ntide<0)flag=1; if(!down&&deep[now]+k>l)flag=1; else if(!down&&deep[now]+k<=l)down=!down; tide=ntide;now++; } if(tide==0||tide==k)down=!down; if(down)tide--; else tide++; if(flag)break; } if(flag)break; } if(flag)cout<<"No"<<endl; else cout<<"Yes"<<endl; } }
|