【牛客 - 331D】炫酷路途(二进制枚举 或 建图方式+最短路 或 dfs)
生活随笔
收集整理的這篇文章主要介紹了
【牛客 - 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)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 信用卡申请快速下卡 下卡绝招要掌握好
- 下一篇: spybotsd.exe - spybo