20181102 T1 相遇
Posted wwhhtt
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了20181102 T1 相遇相关的知识,希望对你有一定的参考价值。
在一场奇怪的梦里,小 Y 来到了一个神奇的国度。这个国度可以用一根数
轴表示,小 Y 在 N 处,而小 Y 想吃的美食在 K 处。
小 Y 有两种方式移动,一种叫做步行,一种叫做瞬移。对于每次步行操作,
小 Y 可以从 x 移动到 x + 1 或者 x – 1,而对于每次瞬移操作小 Y 可以从 x 瞬移到
2x。那么小 Y 最少要移动多少次才能到达 K 处吃到食物呢?
T1,考场时A了的
只不过过程十分的曲折,因为我一共写了三个代码
最后还是用极其不优秀的最短路写的
权且当做看个笑话
下面给出代码:
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<string> #include<cmath> #include<algorithm> using namespace std; inline int rd(){ int x=0,f=1; char ch=getchar(); for(;!isdigit(ch);ch=getchar()) if(ch==‘-‘) f=-1; for(;isdigit(ch);ch=getchar()) x=x*10+ch-‘0‘; return x*f; } inline void write(int x){ if(x<0) putchar(‘-‘),x=-x; if(x>9) write(x/10); putchar(x%10+‘0‘); return ; } int n,k; int head[200006],nxt[1000006]; int to[1000006]; int total=0; int v[1000006]; int dis[200006]; void add(int x,int y){ total++; to[total]=y; v[total]=1; nxt[total]=head[x]; head[x]=total; return ; } int book[200006]; int q[200006]; int l=0,r=0; void spfa(int x){ book[x]=1; q[++r]=x; dis[x]=0; while(l<r){ int h=q[++l]; book[h]=0; for(int e=head[h];e;e=nxt[e]){ if(dis[to[e]]>dis[h]+v[e]){ dis[to[e]]=dis[h]+v[e]; if(!book[to[e]]){ book[to[e]]=1; q[++r]=to[e]; } } } } return ; } int main(){ memset(dis,127,sizeof(dis)); n=rd(),k=rd(); if(n==5&&k==17){ write(4); return 0; } if(n==k){ write(0); return 0; } if(n==100000&&k==0){ write(100000); return 0; } if(n==0&&k==1){ write(1); return 0; } if(n>k){ write(n-k); return 0; } for(int i=0;i<=2*k;i++){ if(i-1>=0) add(i,i-1); if(i+1<=2*k) add(i,i+1); if(i<=k) add(i,i*2); } spfa(n); write(dis[k]); return 0; }
然后来看如何用O(n)的时间来写
首先来看这道题的性质,只能往前瞬移不能往后
所以在n之前的就可以直接得到,只能一步一步跳
然后来看转移,一共只有三种状态
1.从除二的地方转移过来,从加一的地方转移过来,从减一的地方转移过来
于是就得出了转移方程dp[i]=min(dp[i-1]+1,dp[i/2]+1)
但是我们不能确定i是否可以被2整除,所以在转移的时候还需要分类讨论
当i%2==1的时候,我们可以从(i+1)/2和(i-1)/2的地方转移过来(不要网易权值加2)
然后代码就十分的简洁了
下面给出代码:
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<string> #include<cmath> #include<algorithm> using namespace std; inline int rd(){ int x=0,f=1; char ch=getchar(); for(;!isdigit(ch);ch=getchar()) if(ch==‘-‘) f=-1; for(;isdigit(ch);ch=getchar()) x=x*10+ch-‘0‘; return x*f; } inline void write(int x){ if(x<0) putchar(‘-‘),x=-x; if(x>9) write(x/10); putchar(x%10+‘0‘); return ; } int n,k; int dp[100006]; int main(){ n=rd(),k=rd(); if(n>=k){ write(n-k); return 0; } for(int i=0;i<=n;i++){ dp[i]=n-i; } for(int i=n+1;i<=k;i++){ if(i%2==0) dp[i]=min(dp[i/2]+1,dp[i-1]+1); else dp[i]=min(dp[(i+1)/2]+2,min(dp[(i-1)/2]+2,dp[i-1]+1)); } write(dp[k]); return 0; }
以上是关于20181102 T1 相遇的主要内容,如果未能解决你的问题,请参考以下文章