【BZOJ2259】[Oibh]新型计算机 最短路

【BZOJ2259】[Oibh]新型计算机

Description

Tim正在摆弄着他设计的“计算机”,他认为这台计算机原理很独特,因此利用它可以解决许多难题。 
但是,有一个难题他却解决不了,是这台计算机的输入问题。新型计算机的输入也很独特,假设输入序列中有一些数字(都是自然数——自然数包括0),计算机先读取第一个数字S1,然后顺序向后读入S1个数字。接着再读一个数字S2,顺序向后读入S2个数字……依此类推。不过只有计算机正好将输入序列中的数字读完,它才能正确处理数据,否则计算机就会进行自毁性操作! 
Tim现在有一串输入序列。但可能不是合法的,也就是可能会对计算机造成破坏。于是他想对序列中的每一个数字做一些更改,加上一个数或者减去一个数,当然,仍然保持其为自然数。使得更改后的序列为一个新型计算机可以接受的合法序列。 
不过Tim还希望更改的总代价最小,所谓总代价,就是对序列中每一个数操作的参数的绝对值之和。 
写一个程序: 
 从文件中读入原始的输入序列; 
 计算将输入序列改变为合法序列需要的最小代价; 
 向输出文件打印结果。 

Input

输入文件包含两行,第一行一个正整数N,N<1 000 001。 
输入文件第二行包含N个自然数,表示输入序列。 

Output

仅一个整数,表示把输入序列改变为合法序列需要的最小代价,保证最小代价小于109。 

Sample Input

4
2 2 2 2

Sample Output

1

题解:一开始以为是DP+树状数组,后来发现竟然是最短路~

从i向i+s1+1连一条边权为0的边,在从i+s1+1向两边连边权为1的边,注意不要重复连边,修改后的s1不能是负数

#include <cstdio>
#include <iostream>
#include <cstring>
#include <queue>
#include <utility>
#define mp(A,B)	make_pair(A,B)
using namespace std;
const int maxn=1000010;
priority_queue<pair<int,int> > pq;
int dis[maxn],lv[maxn],rv[maxn],to[maxn<<2],next[maxn<<2],head[maxn],val[maxn<<2],vis[maxn];
int n,m,cnt;
void add(int a,int b,int c)
{
	to[cnt]=b,val[cnt]=c,next[cnt]=head[a],head[a]=cnt++;
}
int main()
{
	scanf("%d",&n);
	int i,j,u;
	memset(head,-1,sizeof(head));
	for(i=1;i<=n;i++)
	{
		scanf("%d",&u);
		if(i+u>n)	add(i,n+1,i+u-n);
		else	add(i,i+u+1,0);
		for(j=i+1;j<=i+u+1&&j<=n&&!lv[j];j++)	lv[j]=1,add(j,j-1,1);
		for(j=i+u+1;j<=n&&!rv[j];j++)	rv[j]=1,add(j,j+1,1);
	}
	memset(dis,0x3f,sizeof(dis));
	pq.push(mp(0,1)),dis[1]=0;
	while(!pq.empty())
	{
		u=pq.top().second,pq.pop();
		if(vis[u])	continue;
		vis[u]=1;
		for(i=head[u];i!=-1;i=next[i])
			if(dis[to[i]]>dis[u]+val[i])
				dis[to[i]]=dis[u]+val[i],pq.push(mp(-dis[to[i]],to[i]));
	}
	printf("%d",dis[n+1]);
	return 0;
}
posted @ 2017-05-19 14:53  CQzhangyu  阅读(501)  评论(0编辑  收藏  举报