垃圾题目,毁我青春!
题目描述 Description
【Shadow 1】第二题
Shadow最近知道了图灵机是什么(Shadow:就是一行格子和一个机器头移来移去的呗!),于是他突发奇想,创造了一个新游戏——“图灵机游戏”(Shadow:好听吧?)。
游戏规则如下:
在一条长长的纸上有N个格子,每个格子上都有一个数,第i格的数记为Ai,机器头刚开始在第1格。这个游戏有两个操作:
1.如果现在在第i格,则可以移动机器头到第Ai格;
2.把某个Ai减少或增加1。
然而,fotile96看了之后却不以为然。“嗯,你挑战一下用最少次数使机器头到达第N格吧,这样好玩些……”
现在,Shadow已经快Crazy了。于是,Shadow把脸转向了你……
输入描述 Input Description
第1行,1个整数N;
第2行,N个整数Ai。
输出描述 Output Description
1行,1个整数,为最少的操作次数。
样例输入 Sample Input
5
3 4 2 5 3
样例输出 Sample Output
3
数据范围及提示 Data Size & Hint
对于30%的数据,1≤N≤10;
对于60%的数据,1≤N≤1000;
对于100%的数据,1≤N≤100000,1≤Ai≤N。
样例解释
1.先将第1格的值加1
2.跳到第4格
3.跳到第5格,结束游戏
垃圾题目垃圾题目垃圾垃圾真垃圾!!!!
这个题大家可以看出来是最短路吧……
关键是建图……
所以说怎么建呢?
我一开始的想法是相邻两个点可以建图。
于是代码
#include<iostream>
#include<queue>
#include<cstdio>
#include<algorithm>
using namespace std;
struct Edge
{
int ff,tt,next;
}edge[300010];
int tot,head[100010],dist[100010],n;
void build(int ff,int tt)
{
edge[++tot].ff=ff;
edge[tot].tt=tt;
edge[tot].next=head[ff];
head[ff]=tot;
}
queue<int>q;
bool vis[100010];
void spfa()
{
q.push(1);
vis[1]=1;
dist[1]=0;
while(!q.empty())
{
int x=q.front();
q.pop();
vis[x]=0;
for(int i=head[x];i;i=edge[i].next)
{
Edge e=edge[i];
if(dist[e.tt]>dist[x]+1)
{
dist[e.tt]=dist[x]+1;
if(!vis[e.tt])
{
q.push(e.tt);
vis[e.tt]=1;
}
}
}
}
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
if(i!=1)build(i,i-1);
if(i!=n)build(i,i+1);
dist[i]=0x7fffffff;
}
for(int i=1;i<=n;i++)
{
int a;
cin>>a;
build(i,a);
}
spfa();
cout<<dist[n];
return 0;
}
交!不交就是怂!怂就是A不了!
然后……
嘿嘿嘿~
第二个想法,我要每个点两两间建一条双向边……带权值……
然后……好像要开100000*100000的数组? (╯‵□′)╯︵┻━┻
肯定不行啊啊啊啊啊啊啊啊啊啊啊啊啊
第三个想法……试着调整一下建边数量
建少一点似乎很有趣?
于是代码
#include<iostream>
#include<queue>
#include<cstdio>
#include<algorithm>
using namespace std;
struct Edge
{
int ff,tt,next,dd;
}edge[1000010];
int tot,head[100010],dist[100010],n;
void build(int ff,int tt,int dd)
{
edge[++tot].ff=ff;
edge[tot].tt=tt;
edge[tot].dd=dd;
edge[tot].next=head[ff];
head[ff]=tot;
}
queue<int>q;
bool vis[100010];
void spfa()
{
q.push(1);
vis[1]=1;
dist[1]=0;
while(!q.empty())
{
int x=q.front();
q.pop();
vis[x]=0;
for(int i=head[x];i;i=edge[i].next)
{
Edge e=edge[i];
if(dist[e.tt]>dist[x]+e.dd)
{
dist[e.tt]=dist[x]+e.dd;
if(!vis[e.tt])
{
q.push(e.tt);
vis[e.tt]=1;
}
}
}
}
}
int main()
{
cin>>n;
for(int i=0;i<=n;i++)dist[i]=0x7fffffff;
for(int i=1;i<=n;i++)
{
int a;
cin>>a;
for(int j=a-4;j<=a+4;j++)
{
build(i,j,abs(j-a)+1);
}
}
spfa();
cout<<dist[n];
return 0;
}
交!不交就是怂!怂就是A不了!
然后……
好吧……好歹分多了
于是加上点想法
我们是不是可以判断一下当前点到达终点的权值来做……
于是代码
#include<iostream>
#include<queue>
#include<cstdio>
#include<algorithm>
using namespace std;
struct Edge
{
int ff,tt,next,dd;
}edge[1000010];
int tot,head[100010],dist[100010],n;
void build(int ff,int tt,int dd)
{
edge[++tot].ff=ff;
edge[tot].tt=tt;
edge[tot].dd=dd;
edge[tot].next=head[ff];
head[ff]=tot;
}
queue<int>q;
bool vis[100010];
void spfa()
{
q.push(1);
vis[1]=1;
dist[1]=0;
while(!q.empty())
{
int x=q.front();
q.pop();
vis[x]=0;
for(int i=head[x];i;i=edge[i].next)
{
Edge e=edge[i];
if(dist[e.tt]>dist[x]+e.dd)
{
dist[e.tt]=dist[x]+e.dd;
if(!vis[e.tt])
{
q.push(e.tt);
vis[e.tt]=1;
}
}
}
}
}
int main()
{
cin>>n;
for(int i=0;i<=n;i++)dist[i]=0x7fffffff;
for(int i=1;i<=n;i++)
{
int a;
cin>>a;
for(int j=a-4;j<=a+4;j++)
{
build(i,j,abs(j-a)+1);
}
build(i,n,abs(n-a)+1);
}
spfa();
cout<<dist[n];
return 0;
}
再交!
垃圾题!
本题的难点在于如何建图,只要建出图来一切好说……
垃圾出题人!