【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
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; }
| 欢迎来原网站坐坐! >原文链接<