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