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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【牛客 - 331D】炫酷路途(二进制枚举 或 建图方式+最短路 或 dfs)

發布時間:2023/12/10 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【牛客 - 331D】炫酷路途(二进制枚举 或 建图方式+最短路 或 dfs) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題干:
?

小希現在要從寢室趕到機房,路途可以按距離分為N段,第i個和i+1個是直接相連的,只需要一秒鐘就可以相互到達。

炫酷的是,從第i個到第i+2pi+2p個也是直接相連的(其中p為任意非負整數),只需要一秒鐘就可以相互到達。

更炫酷的是,有K個傳送法陣使得某些u,v之間也是直接相連的,只需要一秒鐘就可以相互到達,當然,由于設備故障,可能會有一些u=v的情況發生。

現在小希為了趕路,她需要在最短的時間里從寢室(編號為1)到達機房(編號為N),她不希望到達這N個部分以外的地方(不能到達位置N+1),也不能走到比自己當前位置編號小的地方(比如從5走到3是非法的)。

她想知道最短的時間是多少。

輸入描述:

第一行輸入兩個整數N,K,表示路途的段數和傳送法陣的數量。從第二行開始K行,每行兩個整數aiai,bibi表示兩個位置之間相連。 2≤N≤1,000,000,0002≤N≤1,000,000,0000≤K≤150≤K≤15

輸出描述:

輸出一個整數,表示從寢室到機房最短的時間是多少秒。

示例1

輸入

復制

12 2 1 5 6 6

輸出

復制

3

示例2

輸入

復制

17 2 2 5 8 9

輸出

復制

1

?

解題報告:

? ? 兩種方法差不多快,,因為數據比較小,,最多也就30步左右、、所以怎么寫都行

AC代碼1:

#include<cstdio> #include<iostream> #include<algorithm> #include<queue> #include<map> #include<vector> #include<set> #include<string> #include<cmath> #include<cstring> #define ll long long #define pb push_back #define pm make_pair #define fi first #define se second using namespace std; const int MAX = 2e5 + 5; struct Node {ll u,v; } node[55],use[55]; ll db[55],qi[55]; const ll mod = 1e9+7; ll qpow(ll a, ll k) {ll res = 1;while(k) {if(k&1) res = (a*res)%mod;k>>=1;a = (a*a)%mod;}return res; } bool cmp(Node a,Node b) {if(a.u != b.u) return a.u < b.u;else return a.v < b.v; } ll go(ll cur,ll tar) {ll res = 0;tar = tar - cur;cur = 0;for(int i = 33; i>=0 && cur != tar; i--) {if(cur + db[i] <= tar) res++,cur += db[i];}return res; } int main() {db[0] = 1;//printf("%d",1<<1);for(ll i = 1; i<=40; i++) db[i] = db[i-1]*2;ll n,k;cin>>n>>k;for(int i = 0; i<k; i++) {scanf("%lld %lld",&node[i].u,&node[i].v);if(node[i].u == node[i].v || node[i].u > n || node[i].v > n) {k--,i--;continue;}if(node[i].u > node[i].v) swap(node[i].u,node[i].v);}sort(node,node+k,cmp);ll up = qpow(2,k),ans = 0x3f3f3f3f;for(ll bit = 0; bit<up; bit++) {int tot = 0;for(int i = 0; i<k; i++) {if( ( (1<<i) & bit ) != 0) use[++tot] = node[i],qi[tot] = node[i].u;}ll now = 1,step = 0;while(now <= n) {if(now == n) break;if(now > qi[tot]) {step += go(now,n);break;}int pos = lower_bound(qi+1,qi+tot+1,now) - qi;if(qi[pos] == now) step++,now = use[pos].v;else step += go(now,qi[pos]),now = qi[pos];}ans = min(step,ans);}printf("%lld\n",ans);return 0 ;} /* 14 2 1 14 1 13 2 */

注意這種方式第一次被坑了,,if( ( (1<<i) & bit ) != 0)這一句 剛開始寫的是==1? 這樣就錯了,,因為你&運算時,非零不代表是1、、之前也在這錯過、、這次一定要記住了,就寫if((1<<i) & bit ) 多好、、

不過人家寫的好短、、、應該是我多考慮了很多情況、(然而這個代碼忘了讀入的時候判斷u和v的大小)

#include<bits/stdc++.h> using namespace std; struct Node {int u, v;bool operator < (const Node& node) const {return u <= node.u;} } node[20]; int step(int d) {int ans = 0;while(d) {d -= d & -d;ans++;}return ans; } int main() {int n, k; scanf("%d%d", &n, &k);for(int i = 0; i < k; i++) scanf("%d%d", &node[i].u, &node[i].v);sort(node, node+k);int ans = step(n-1);for(int i = 0; i < 1<<k; i++) {int x = 1, tmp = 0;for(int j = 0; j < k; j++) {if(i & 1<<j) {if(x > node[j].u) continue;tmp += step(node[j].u-x) + 1;x = node[j].v;}}if(x > n) continue;tmp += step(n-x);ans = min(ans, tmp);}printf("%d\n", ans);return 0; }

AC代碼2:(建圖最短路)

#include<cstdio> #include<iostream> #include<algorithm> #include<queue> #include<map> #include<vector> #include<set> #include<string> #include<cmath> #include<cstring> #define ll long long #define pb push_back #define pm make_pair #define fi first #define se second using namespace std; const int MAX = 2e5 + 5; const int INF = 0x3f3f3f3f; int a[MAX]; int dis[MAX]; int tot; struct Node {ll u,v; } node[MAX]; int main() {int n,k;int tmp1,tmp2;cin>>n>>k;for(int i =1; i<=k; i++) {scanf("%d %d",&tmp1,&tmp2);if(tmp1 == tmp2 || tmp1 > n || tmp2 > n) {k--,i--;continue;}node[i].u = tmp1,node[i].v = tmp2;if(node[i].u > node[i].v) swap(node[i].u,node[i].v);a[++tot] = tmp1,a[++tot] = tmp2;}a[++tot] = 1;a[++tot] = n;sort(a+1,a+tot+1);int x = unique(a+1,a+tot+1) - a - 1;memset(dis,INF,sizeof dis); //求出1到另外一點的最短路 dis[1] = 0;for(int i = 1; i<=x; i++) {for(int j = i+1; j<=x; j++) {for(int q = 1; q<=k; q++) {if(a[i] == node[q].u && a[j] == node[q].v) dis[j] = min(dis[i]+1,dis[j]);} dis[j] = min(dis[i] + __builtin_popcount(a[j] - a[i]),dis[j]);}}printf("%d\n", dis[x]);return 0 ;}

AC代碼3:(dfs這題也很快)

#include <bits/stdc++.h> using namespace std; #define LL long long #define mod 998244353 #define MAXN 1000005 const int INF = 0x3f3f3f3f; int n,k; struct no{int s,e; }path[16];int go(int x){int r=0;while(x){if(x%2==1) r++;x=x/2;}return r; } int dfs(int pos,int L,int R){if(pos==k+1) return go(R-L);int ll=path[pos].s,rr=path[pos].e;int s1=dfs(pos+1,L,R),s2 = INF;if(ll>=L&&rr<=R){s2=dfs(pos+1,L,ll)+dfs(pos+1,rr,R)+1;}return min(s1,s2); } int main() {scanf("%d%d",&n,&k);for(int i=1;i<=k;i++){scanf("%d%d",&path[i].s,&path[i].e);if(path[i].s > path[i].e) swap(path[i].s,path[i].e);}cout<<dfs(1,1,n);return 0; }

?

總結

以上是生活随笔為你收集整理的【牛客 - 331D】炫酷路途(二进制枚举 或 建图方式+最短路 或 dfs)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。