BZOJ2259[Oibh] 新型計算機
阿新 • • 發佈:2018-11-08
原題連結:https://www.lydsy.com/JudgeOnline/problem.php?id=2259
新型計算機
Description
Tim正在擺弄著他設計的“計算機”,他認為這臺計算機原理很獨特,因此利用它可以解決許多難題。
但是,有一個難題他卻解決不了,是這臺計算機的輸入問題。新型計算機的輸入也很獨特,假設輸入序列中有一些數字(都是自然數——自然數包括0),計算機先讀取第一個數字S1,然後順序向後讀入S1個數字。接著再讀一個數字S2,順序向後讀入S2個數字……依此類推。不過只有計算機正好將輸入序列中的數字讀完,它才能正確處理資料,否則計算機就會進行自毀性操作!
Tim現在有一串輸入序列。但可能不是合法的,也就是可能會對計算機造成破壞。於是他想對序列中的每一個數字做一些更改,加上一個數或者減去一個數,當然,仍然保持其為自然數。使得更改後的序列為一個新型計算機可以接受的合法序列。
不過Tim還希望更改的總代價最小,所謂總代價,就是對序列中每一個數操作的引數的絕對值之和。
寫一個程式:
從檔案中讀入原始的輸入序列;
計算將輸入序列改變為合法序列需要的最小代價;
向輸出檔案列印結果。
Input
輸入檔案包含兩行,第一行一個正整數
,
。
輸入檔案第二行包含
個自然數,表示輸入序列。
Output
僅一個整數,表示把輸入序列改變為合法序列需要的最小代價,保證最小代價小於 。
Sample Input
4
2 2 2 2
Sample Output
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();}