日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

I. Intersections

發(fā)布時(shí)間:2023/12/3 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 I. Intersections 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

I. Intersections

題意:

n行,m列,n * m個(gè)交點(diǎn),當(dāng)我們處于交點(diǎn)(i,j),
如果當(dāng)前時(shí)間位于[k * aij + k * bij , (k+1) * aij + k * bij ),我們可以上下移動
如果當(dāng)前處于[(k+1)* aij + k * bij , (k+1) * aij + (k+1) * bij ],我們可以左右移動
也可以選擇不動
cij表示從(i,j)移動到(i,j+1)的時(shí)間
wij表示從(i,j)移動到(i+1,j)的時(shí)間
問從(xs,ys)到(xt,yt)的最少時(shí)間是多少?

題解:

這個(gè)題肯定是最短路方向,但是和一般最短路不一樣,因?yàn)槟愕姆较蜻x擇受時(shí)間的限制,其實(shí)也不難,但是思維不要被限制,要放開想
我們先從時(shí)間下手,這兩個(gè)時(shí)間區(qū)間合在一起就是[k * aij + k * bij, (k+1) * aij + (k+1) * bij ],一個(gè)周期就是(aij+bij),那么也就可以這樣理解,給一個(gè)時(shí)間tim,x = tim%(aij+bij),如果x小于aij,說明當(dāng)前時(shí)間就位于第一區(qū)間,如果大于等于aij,(也就是到達(dá)bij的區(qū)域)就在第二區(qū)間
tim的求法
ll tim = now.z % (a[x][y] + b[x][y]);
現(xiàn)在我們開始考慮路徑
f[i][j]到點(diǎn)i,j的最短時(shí)間
如果我們要從(x,y)移動到(x-1,y),怎么行動?首先花費(fèi)是固定的w[i-1][j],關(guān)鍵是什么時(shí)間段移動,
如果當(dāng)前時(shí)間在第一時(shí)間段,在這個(gè)區(qū)間里,我們是可以上下移動的,也就是可以立刻行動,所以就是直接求最短路f[x - 1][y] = f[x][y] + w[x - 1][y];
如何當(dāng)前時(shí)間在第二時(shí)間段,我們只能左右移動,根本不能到達(dá)上面,那怎么辦,這個(gè)情況放棄?錯了,這個(gè)時(shí)間段不能向上移動,但是我們說了(aij+bij)是一個(gè)周期,所以我們完全可以等到下一個(gè)周期的第一個(gè)時(shí)間段再向上移動,等待時(shí)間(即原地不動)
ll Tim = a[x][y] + b[x][y] - tim;//這是純等待時(shí)間
f[x - 1][y] = f[x][y] + w[x - 1][y] + Tim;
也就是第一種情況的基礎(chǔ)上算上等待時(shí)間
這是向上走的情況,還有向下,左,右三種情況,一次列出即可,用dij跑最短路就OK了
這樣一看題目簡單多了

代碼:

#include <cstdio> #include <iostream> #include <cstring> #include <vector> #include <unordered_map> #include <cmath> #include <algorithm> #include <queue> using namespace std;typedef long long ll; const int maxn = 505; ll a[maxn][maxn],b[maxn][maxn],c[maxn][maxn],w[maxn][maxn]; ll f[maxn][maxn]; int vis[maxn][maxn];int n,m,sx,sy,ex,ey;struct Node {int x,y;ll z;bool operator < (const Node&rhs) const {return z > rhs.z;} };void dij(int sx,int sy) {priority_queue<Node>q;q.push({sx,sy,0});f[sx][sy] = 0;while(!q.empty()) {Node now = q.top();q.pop();int x = now.x;int y = now.y;if(vis[x][y]) continue;vis[x][y] = 1;ll tim = now.z % (a[x][y] + b[x][y]);if(x > 1) { //往上走if(tim < a[x][y]) {//可以上下移動 if(f[x - 1][y] > f[x][y] + w[x - 1][y]) {f[x - 1][y] = f[x][y] + w[x - 1][y];q.push({x - 1,y,f[x - 1][y]});}} else {//只能左右移動,如果想往上走需要再等Tim這段時(shí)間 ll Tim = a[x][y] + b[x][y] - tim;if(f[x - 1][y] > f[x][y] + w[x - 1][y] + Tim) {f[x - 1][y] = f[x][y] + w[x - 1][y] + Tim;q.push({x - 1,y,f[x - 1][y]});}}}//下面同理與上 if(x < n) { //往下走if(tim < a[x][y]) {if(f[x + 1][y] > f[x][y] + w[x][y]) {f[x + 1][y] = f[x][y] + w[x][y];q.push({x + 1,y,f[x + 1][y]});}} else {ll Tim = a[x][y] + b[x][y] - tim;if(f[x + 1][y] > f[x][y] + w[x][y] + Tim) {f[x + 1][y] = f[x][y] + w[x][y] + Tim;q.push({x + 1,y,f[x + 1][y]});}}}if(y > 1) { //往左走if(tim < a[x][y]) {ll Tim = a[x][y] - tim;if(f[x][y - 1] >= f[x][y] + c[x][y - 1] + Tim) {f[x][y - 1] = f[x][y] + c[x][y - 1] + Tim;q.push({x,y - 1,f[x][y - 1]});}} else {if(f[x][y - 1] > f[x][y] + c[x][y - 1]) {f[x][y - 1] = f[x][y] + c[x][y - 1];q.push({x,y - 1,f[x][y - 1]});}}}if(y < m) { //往右走if(tim < a[x][y]) {ll Tim = a[x][y] - tim;if(f[x][y + 1] >= f[x][y] + c[x][y] + Tim) {f[x][y + 1] = f[x][y] + c[x][y] + Tim;q.push({x,y + 1,f[x][y + 1]});}} else {if(f[x][y + 1] > f[x][y] + c[x][y]) {f[x][y + 1] = f[x][y] + c[x][y];q.push({x,y + 1,f[x][y + 1]});}}}} }int main() {scanf("%d%d%d%d%d%d",&n,&m,&sx,&sy,&ex,&ey);for(int i = 1;i <= n;i++) {for(int j = 1;j <= m;j++) {scanf("%lld",&a[i][j]);}}for(int i = 1;i <= n;i++) {for(int j = 1;j <= m;j++) {scanf("%lld",&b[i][j]);}}for(int i = 1;i <= n;i++) {for(int j = 1;j <= m - 1;j++) {scanf("%lld",&c[i][j]);}}for(int i = 1;i <= n - 1;i++) {for(int j = 1;j <= m;j++) {scanf("%lld",&w[i][j]);}}memset(f,0x3f,sizeof(f));dij(sx,sy);printf("%lld\n",f[ex][ey]);return 0; }

總結(jié)

以上是生活随笔為你收集整理的I. Intersections的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。