BZOJ2259[Oibh] 新型计算机

版权声明:大佬您能赏脸,蒟蒻倍感荣幸,还请联系我让我好好膜拜。 https://blog.csdn.net/ShadyPi/article/details/83175849

原题链接:https://www.lydsy.com/JudgeOnline/problem.php?id=2259

新型计算机

Description

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

Input

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

Output

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

Sample Input

4
2 2 2 2

Sample Output

1

题解

往后读入数字的过程实际上是走了一条权值为 0 0 的边,调整的过程就是往左/右走了一些权值为 1 1 的边。

所以让我们跑跑最短路??

代码
#include<bits/stdc++.h>
#define add(f,t,w) mmp[f].push_back((sd){t,w})
using namespace std;
const int M=1e6+5;
struct sd{int to,w;};
bool operator<(sd a,sd b){return a.w>b.w;}
int que[M],dis[M],n,mn=M;
bool vis[M];
vector<sd>mmp[M];
priority_queue<sd>dui;
void dijkstra(int s)
{
	memset(dis,127,sizeof(dis));dui.push((sd){s,dis[s]=0});
	for(sd f,t;!dui.empty();)
	{
		f=dui.top(),dui.pop();if(vis[f.to])continue;vis[f.to]=1;
		for(int i=mmp[f.to].size()-1;i>=0;--i)if(!vis[(t=mmp[f.to][i]).to]&&dis[t.to]>dis[f.to]+t.w)dis[t.to]=dis[f.to]+t.w,dui.push((sd){t.to,dis[t.to]});
	}
}
void in(){scanf("%d",&n);for(int i=1;i<=n;++i)scanf("%d",&que[i]),mn=min(mn,i+que[i]+1),i+que[i]<=n?add(i,i+que[i]+1,0):add(i,n+1,i+que[i]-n);}
void ac()
{
	if(mn<=n+1)for(int i=mn;i<=n;++i)add(i,i+1,1);
	for(int i=1;i<=n;++i)add(i+1,i,1);
	dijkstra(1);printf("%d",dis[n+1]);
}
int main(){in(),ac();}

猜你喜欢

转载自blog.csdn.net/ShadyPi/article/details/83175849