石油大--2020年秋季組隊訓練賽第十三場----B、Bouldering(最短路)
題面:
題意:
給定一個
h
∗
w
h*w
h∗w 點陣,其中某一些點是可以走的。
這些點都有一個權值,表示如果經過當前點,則會花費的力氣。
給定一個
r
r
r,你只能從當前點到達與你歐幾里得距離不超過
r
r
r 的點。
問在花費的總力氣不超過
s
s
s 的情況下,從最下層的那個點(保證唯一),走到最上層的那個點(保證唯一)距離的最小值。
題解:
對於花費的力氣的總值為:
w
∗
h
∗
9
w*h*9
w∗h∗9,是一個較小的值。
我們可以設
d
p
[
x
]
[
j
]
dp[x][j]
dp[x][j] 為當前走到
x
x
x 號節點,花費力氣為
j
j
j 的最短距離。
然而這樣直接寫會 T L E TLE TLE ,因為會走到很多無用的狀態。
考慮剪枝,如果當前到達 x x x 的最短路是 d i s dis dis,在當前 d i s dis dis 下花費的力氣為 k k k,那麼那些 d i s ′ > = d i s a n d k ′ > = k dis'>=dis\ and\ k'>=k dis′>=dis and k′>=k 的狀態都是無用的,跳過即可。只有 d i s ′ > = d i s a n d k ′ < k dis'>=dis\ and\ k'<k dis′>=dis and k′<k 的那些狀態才可能對於最終答案有貢獻。
#pragma GCC optimize(2)
#pragma GCC optimize("Ofast","inline","-ffast-math")
#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<string>
#include<queue>
#include<bitset>
#include<map>
#include<unordered_map>
#include<set>
namespace onlyzhao
{
#define ui unsigned int
#define ll long long
#define llu unsigned ll
#define ld long double
#define pr make_pair
#define pb push_back
#define lc (cnt<<1)
#define rc (cnt<<1|1)
#define len(x) (t[(x)].r-t[(x)].l+1)
#define tmid ((l+r)>>1)
#define fhead(x) for(int i=head[(x)];i;i=nt[i])
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)>(y)?(y):(x))
#define one(n) for(int i=1;i<=(n);i++)
#define rone(n) for(int i=(n);i>=1;i--)
#define fone(i,x,n) for(int i=(x);i<=(n);i++)
#define frone(i,n,x) for(int i=(n);i>=(x);i--)
#define fonk(i,x,n,k) for(int i=(x);i<=(n);i+=(k))
#define fronk(i,n,x,k) for(int i=(n);i>=(x);i-=(k))
#define two(n,m) for(int i=1;i<=(n);i++) for(int j=1;j<=(m);j++)
#define ftwo(i,n,j,m) for(int i=1;i<=(n);i++) for(int j=1;j<=(m);j++)
#define fvc(vc) for(int i=0;i<vc.size();i++)
#define frvc(vc) for(int i=vc.size()-1;i>=0;i--)
#define forvc(i,vc) for(int i=0;i<vc.size();i++)
#define forrvc(i,vc) for(int i=vc.size()-1;i>=0;i--)
#define cls(a) memset(a,0,sizeof(a))
#define cls1(a) memset(a,-1,sizeof(a))
#define clsmax(a) memset(a,0x3f,sizeof(a))
#define clsmin(a) memset(a,0x80,sizeof(a))
#define cln(a,num) memset(a,0,sizeof(a[0])*num)
#define cln1(a,num) memset(a,-1,sizeof(a[0])*num)
#define clnmax(a,num) memset(a,0x3f,sizeof(a[0])*num)
#define clnmin(a,num) memset(a,0x80,sizeof(a[0])*num)
#define sc(x) scanf("%d",&x)
#define sc2(x,y) scanf("%d%d",&x,&y)
#define sc3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define scl(x) scanf("%lld",&x)
#define scl2(x,y) scanf("%lld%lld",&x,&y)
#define scl3(x,y,z) scanf("%lld%lld%lld",&x,&y,&z)
#define scf(x) scanf("%lf",&x)
#define scf2(x,y) scanf("%lf%lf",&x,&y)
#define scf3(x,y,z) scanf("%lf%lf%lf",&x,&y,&z)
#define scs(x) scanf("%s",x+1)
#define scs0(x) scanf("%s",x)
#define scline(x) scanf("%[^\n]%*c",x+1)
#define scline0(x) scanf("%[^\n]%*c",x)
#define pcc(x) putchar(x)
#define pc(x) printf("%d\n",x)
#define pc2(x,y) printf("%d %d\n",x,y)
#define pc3(x,y,z) printf("%d %d %d\n",x,y,z)
#define pck(x) printf("%d ",x)
#define pcl(x) printf("%lld\n",x)
#define pcl2(x,y) printf("%lld %lld\n",x,y)
#define pcl3(x,y,z) printf("%lld %lld %d\n",x,y,z)
#define pclk(x) printf("%lld ",x)
#define pcf2(x) printf("%.2f\n",x)
#define pcf6(x) printf("%.6f\n",x)
#define pcf8(x) printf("%.8f\n",x)
#define pcs(x) printf("%s\n",x+1)
#define pcs0(x) printf("%s\n",x)
#define pcline(x) printf("%d**********\n",x)
#define casett int tt;sc(tt);int pp=0;while(tt--)
char buffer[100001],*S,*T;
inline char Get_Char()
{
if (S==T)
{
T=(S=buffer)+fread(buffer,1,100001,stdin);
if (S==T) return EOF;
}
return *S++;
}
inline int read()
{
char c;int re=0;
for(c=Get_Char();c<'0'||c>'9';c=Get_Char());
while(c>='0'&&c<='9') re=re*10+(c-'0'),c=Get_Char();
return re;
}
};
using namespace onlyzhao;
using namespace std;
const int inf=0x3f3f3f3f;
const ll lnf=0x3f3f3f3f3f3f3f3f;
const double dnf=1e9;
const int mod=998244353;
const double eps=1e-9;
const double pi=acos(-1.0);
const int hp=13331;
const int maxn=1000100;
const int maxm=100100;
const int up=100100;
double dp[25*25+100][25*25*9+100];
bool ha[25*25+100][25*25*9+100];
int h,w,r,ss;
pair<int,int>p[25*25+100],s,t;
pair<double,int>pp[25*25+100];
int cnt=0,ans=0;
char str[55][55];
int head[maxn],ver[maxn],nt[maxn],val[maxn],tot=1;
double edge[maxn];
void add(int x,int y,double z)
{
ver[++tot]=y,edge[tot]=z;
nt[tot]=head[x],head[x]=tot;
}
int p2(int x)
{
return x*x;
}
int dis(int i,int j)
{
return p2(p[i].first-p[j].first)+p2(p[i].second-p[j].second);
}
int sgn(double x)
{
if(abs(x)<eps) return 0;
else if(x>0) return 1;
else return -1;
}
struct node
{
double dis;
int x,val;
friend bool operator < (const node &a,const node &b)
{
if(sgn(a.dis-b.dis)!=0) return a.dis>b.dis;
return a.val>b.val;
}
node(){}
node(double a,int b,int c)
{
dis=a,x=b,val=c;
}
};
void dij(int s)
{
for(int i=1;i<=cnt;i++)
{
for(int j=0;j<=ans;j++)
dp[i][j]=dnf,ha[i][j]=false;
}
dp[s][val[s]]=0;
priority_queue<node> q;
q.push(node(0.0,s,val[s]));
while(q.size())
{
int x=q.top().x;
int vv=q.top().val;
q.pop();
if(ha[x][vv]) continue;
ha[x][vv]=true;
if(pp[x].first>dp[x][vv])
{
pp[x].first=dp[x][vv];
pp[x].second=vv;
}
for(int i=head[x];i;i=nt[i])
{
int y=ver[i];
double z=edge[i];
int nowc=val[y];
if(vv+nowc>ans) continue;
if(dp[x][vv]+z>=pp[y].first&&vv+nowc>=pp[y].second) continue;
if(dp[y][vv+nowc]>dp[x][vv]+z)
{
dp[y][vv+nowc]=dp[x][vv]+z;
q.push(node(dp[y][vv+nowc],y,vv+nowc));
}
}
}
}
int main(void)
{
scanf("%d%d%d%d",&h,&w,&r,&ss);
s.first=-1;
t.first=inf;
for(int i=1;i<=h;i++)
{
scanf("%s",str[i]+1);
for(int j=1;j<=w;j++)
{
if(str[i][j]=='.') continue;
str[i][j]-='0';
ans+=str[i][j];
p[++cnt]=pr(i,j);
val[cnt]=str[i][j];
if(p[cnt].first>s.first)
{
s.first=p[cnt].first;
s.second=cnt;
}
if(p[cnt].first<t.first)
{
t.first=p[cnt].first;
t.second=cnt;
}
}
}
ans=min(ans,ss);
for(int i=1;i<=cnt;i++)
{
pp[i].first=dnf;
for(int j=1;j<=cnt;j++)
{
if(i==j) continue;
if(dis(i,j)>r*r) continue;
add(i,j,sqrt(dis(i,j)));
add(j,i,sqrt(dis(i,j)));
}
}
dij(s.second);
int tt=t.second;
double minn=dnf;
for(int i=0;i<=ans&&i<=ss;i++)
minn=min(minn,dp[tt][i]);
if(minn+10>=dnf) printf("impossible\n");
else printf("%.15f\n",minn);
return 0;
}
相關文章
- 中國石油大學新生訓練賽第四場:Dominoc
- 10.5組隊訓練賽-2024CCPC山東省賽
- 中石油訓練賽 - Historical Maths(二分)
- 第十三屆藍橋杯省賽C/C++ B組C++
- 2024.11.9組隊訓練題解記錄
- 4.17訓練賽
- ZZJC新生訓練賽第七場題解
- ZZJC新生訓練賽第九場題解
- ZZJC新生訓練賽第二場題解
- ZZJC新生訓練賽第十八場題解
- 100+隊伍逐鹿大獎,創新程式設計挑戰賽秋季賽圓滿落幕程式設計
- 第十三屆藍橋杯省賽A組
- 東北林業大學第15屆校賽(大一組)+雜題+訓練一
- 2018世界盃小組賽B組出線球隊和出局球隊分別是哪些?
- 2020牛客NOIP賽前訓練營-普及組第一場牛牛的跳跳棋題解
- 團隊訓練記錄2024.10.5
- 【vjudge訓練記錄】11月個人訓練賽1
- 2013年省賽b組
- [2019藍橋杯國賽B組c++][最優包含][排列數][第八大奇蹟]C++
- 最短路:求最長最短路
- 最短路 || 最長路 || 次短路
- 位元組豆包大模型團隊突破殘差連線侷限!預訓練收斂最快加速80%大模型
- 如何組織一場JAVA技能大練兵Java
- 2018王者榮耀KPL秋季賽賽程表 2018王者榮耀KPL秋季賽賽制
- 20241114 NOIP訓練賽 T3
- 2024.09.19短時訓練賽總結
- 2024~2025 賽季訓練日誌
- 華南攻略 | GBase資料庫訓練營專場培訓最後一季資料庫
- Llama3訓練每3小時崩一次?豆包大模型、港大團隊為脆皮萬卡訓練提效大模型
- 提高組雜題訓練1
- DeepMind讓AI組隊踢足球學會“合作”,並開源訓練環境AI
- 程式碼隨想錄演算法訓練營第十三天演算法
- 求組隊,PK華為HMS全球應用創新大賽!
- 2020藍橋杯省賽B組C++(第二場)真題C++
- 2018藍橋杯省賽B組
- 2017省賽藍橋杯B組
- 監控大模型訓練大模型
- 【牛客訓練記錄】中國地質大學(武漢)2024年新生賽(同步賽)