再卖菜
问题描述
在一条街上有n个卖菜的商店,按1至n的顺序排成一排,这些商店都卖一种蔬菜。
第一天,每个商店都自己定了一个价格。店主们希望自己的菜价和其他商店的一致,第二天,每一家商店都会根据他自己和相邻商店的价格调整自己的价格。具体的,每家商店都会将第二天的菜价设置为自己和相邻商店第一天菜价的平均值(用去尾法取整)。
注意,编号为1的商店只有一个相邻的商店2,编号为n的商店只有一个相邻的商店n-1,其他编号为i的商店有两个相邻的商店i-1和i+1。
给定第一天各个商店的菜价,请计算第二天每个商店的菜价。
输入格式
输入的第一行包含一个整数n,表示商店的数量。
第二行包含n个整数,依次表示每个商店第一天的菜价。
输出格式
输出一行,包含n个正整数,依次表示每个商店第二天的菜价。
样例输入
8
4 1 3 1 6 5 17 9
样例输出
2 2 1 3 4 9 10 13
数据规模和约定
对于所有评测用例,2 ≤ n ≤ 1000,第一天每个商店的菜价为不超过10000的正整数。
题解:
字典序最小就是提醒我们求最长路。然后把方程式都写成大于等于的样子。最后确定一个绝对大小并检查是否能从起点到所有的点。最后跑一下图就可以了。
#include <bits/stdc++.h>
using namespace std;
const int N=1000;
int ne[N],head[N],w[N],cnt,e[N];
int a[N],dis[N],vis[N],con[N],n;
void add(int a,int b,int c)
{
w[cnt]=c,e[cnt]=b,ne[cnt]=head[a],head[a]=cnt++;
}
void spfa()
{
memset(dis,-0x3f3f3f3f,sizeof dis);
queue<int> q;
q.push(0);
vis[0]=1;
dis[0]=0;
while (!q.empty()){
int u=q.front(); q.pop();
vis[u]=0;
for(int i=head[u];~i;i=ne[i]){
int j=e[i];
con[j]=con[u]+1;
if(con[j]>=n) break;
if(dis[j]<=dis[u]+w[i]){
dis[j]=w[i]+dis[u];
if(!vis[j]) {
q.push(j);
vis[j]=1;
}
}
}
}
}
int main()
{
memset(head,-1,sizeof head);
cin>>n;
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
add(0,2,2*a[1]);
add(2,0,-(2*a[1]+1));
for(int i=2;i<n;i++){
add(i-2,i+1,3*a[i]);
add(i+1,i-2,-(3*a[i]+2));
}
add(n-2,n,2*a[n]);
add(n,n-2,-(2*a[n]+1));
for(int i=1;i<=n;i++) add(i-1,i,1);
spfa();
for(int i=1;i<=n;i++) cout<<dis[i]-dis[i-1]<<' ';
}