BZOJ2259[Oibh] 新型计算机

6 篇文章 0 订阅
4 篇文章 0 订阅

原题链接:https://www.lydsy.com/JudgeOnline/problem.php?id=2259

新型计算机

Description

Tim正在摆弄着他设计的“计算机”,他认为这台计算机原理很独特,因此利用它可以解决许多难题。
但是,有一个难题他却解决不了,是这台计算机的输入问题。新型计算机的输入也很独特,假设输入序列中有一些数字(都是自然数——自然数包括0),计算机先读取第一个数字S1,然后顺序向后读入S1个数字。接着再读一个数字S2,顺序向后读入S2个数字……依此类推。不过只有计算机正好将输入序列中的数字读完,它才能正确处理数据,否则计算机就会进行自毁性操作!
Tim现在有一串输入序列。但可能不是合法的,也就是可能会对计算机造成破坏。于是他想对序列中的每一个数字做一些更改,加上一个数或者减去一个数,当然,仍然保持其为自然数。使得更改后的序列为一个新型计算机可以接受的合法序列。
不过Tim还希望更改的总代价最小,所谓总代价,就是对序列中每一个数操作的参数的绝对值之和。
写一个程序:
 从文件中读入原始的输入序列;
 计算将输入序列改变为合法序列需要的最小代价;
 向输出文件打印结果。

Input

输入文件包含两行,第一行一个正整数 N N N N &lt; 1000001 N&lt;1 000 001 N<1000001
输入文件第二行包含 N N N个自然数,表示输入序列。

Output

仅一个整数,表示把输入序列改变为合法序列需要的最小代价,保证最小代价小于 1 0 9 10^9 109

Sample Input

4
2 2 2 2

Sample Output

1

题解

往后读入数字的过程实际上是走了一条权值为 0 0 0的边,调整的过程就是往左/右走了一些权值为 1 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();}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ShadyPi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值