zoukankan      html  css  js  c++  java
  • BZOJ_2259_ [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

    Sample Output


    1


    暴力的话从i到i+a[i]+1连一条0的边,向两边连对应代价的边。

    这样边数是O(n^2)的,考虑只保留有用的边,只保留i->i+1(1)或i->i-1(1)。

    首先,从左到右的边一定都连,因为a[i]>=0。

    从右往左的边只保留一部分,即从最小的i+a[i]+1开始,到最后。

    这样连边就没问题了,跑dij即可。

    代码:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cstdlib>
    #include <ext/pb_ds/priority_queue.hpp>
    using namespace std;
    using namespace __gnu_pbds;
    #define N 1000050
    inline char nc() {
    	static char buf[100000],*p1,*p2;
    	return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
    }
    int rd() {
    	int x=0; char s=nc();
    	while(s<'0'||s>'9') s=nc();
    	while(s>='0'&&s<='9') x=(x<<3)+(x<<1)+s-'0',s=nc();
    	return x;
    }
    int n,is[N],head[N],to[N<<2],nxt[N<<2],val[N<<2],cnt,a[N],dis[N],vis[N];
    inline void add(int u,int v,int w) {
    	to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt; val[cnt]=w;
    }
    __gnu_pbds::priority_queue<pair<int,int> >q;
    int main() {
    	n=rd();
    	int i,x,mn=1<<30;	
    	for(i=1;i<=n;i++) {
    		a[i]=rd();
    		x=i+a[i]+1;
    		if(x<=n+1) add(i,x,0);
    		else add(i,n+1,x-n-1);
    		mn=min(mn,x);
    	}
    	for(i=2;i<=n;i++) add(i,i-1,1);
    	for(i=mn;i<=n;i++) add(i,i+1,1); 
    	memset(dis,0x3f,sizeof(dis)); 
    	dis[1]=0;
    	q.push(make_pair(0,1));
    	while(!q.empty()) {
    		x=q.top().second; q.pop();
    		if(vis[x]) continue;
    		vis[x]=1;
    		for(i=head[x];i;i=nxt[i]) {
    			if(dis[to[i]]>dis[x]+val[i]) {
    				dis[to[i]]=dis[x]+val[i];
    				q.push(make_pair(-dis[to[i]],to[i]));
    			}
    		}
    	}
    	printf("%d
    ",dis[n+1]);
    }
    
  • 相关阅读:
    数组去重的方法
    ES5-ES8 数组拥有的方法
    常用的git操作命令
    vue中使用vue-echarts
    js的深复制与浅复制
    express 4.x 搭建Node项目框架
    网页布局分类
    shadow---实例
    animate动画解析
    3d------正方体
  • 原文地址:https://www.cnblogs.com/suika/p/9427197.html
Copyright © 2011-2022 走看看