1. 程式人生 > >BZOJ2259[Oibh] 新型計算機

BZOJ2259[Oibh] 新型計算機

原題連結: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();}