201809-4 | |
试题名称: | 再卖菜 |
时间限制: | 1.0s |
内存限制: | 256.0MB |
问题描述: | 问题描述 在一条街上有n个卖菜的商店,按1至n的顺序排成一排,这些商店都卖一种蔬菜。 输入格式 输入的第一行包含一个整数n,表示商店的数量。 输出格式 输出一行,包含n个正整数,依次表示每个商店第一天的菜价。 样例输入 8 样例输出 2 2 2 1 6 5 16 10 数据规模和约定 对于30%的评测用例,2<=n<=5,第二天每个商店的菜价为不超过10的正整数; |
解题思路:这道题可以利用差分约束系统来求解。差分约束系统使用的条件是二元一次不等式,我们将xi-2+xi-1+xi的值看成是一个整体,即dst[i]-dst[i-3];利用题目中的条件,我们可以写出不等式组如下:
另x为第一天的售价,y为第二天的售价,可得
2*y1<=x1+x2<=2*y1+1;
3*y2<=x1+x2+x3<=3*y2+2;
3*y3<=x2+x3+x4<=3*y3+2;
.......
2*yn<=xn-1+xn<=2*yn+1;
由于题目中要求的是字典序最小的,如果选用最短路求解的话,遍历的是最后一组解,是字典序最大的;所以应用最长路求解,写出不等式,spfa与最短路的求解相似
满分代码如下:
#include<bits/stdc++.h>
using namespace std;
const int N=310;
int a[N];//代表第二天的菜价
int dst[N],vst[N];//dst[n]-dst[n-1]=a[n];
int n;//n个商店
//利用邻接表来进行存储
//结构体的存储
struct edge{
int v,next,w;
}e[2006];
int p[N],eid;
void init(){//初始化
memset(p,-1,sizeof(p));
eid=0;
}
//邻接表的插入操作
void insert(int u,int v,int w){
e[eid].v=v;
e[eid].w=w;
e[eid].next=p[u];
p[u]=eid++;
}
void spfa(){
queue<int>q;
for(int i=0;i<=n;i++){
dst[0]=0;
vst[0]=0;
}
q.push(0);
vst[0]=1;
while(!q.empty()){
int x=q.front();
q.pop();
vst[x]=0;
for(int i=p[x];i!=-1;i=e[i].next){
int xx=e[i].v;
if(dst[x]+e[i].w>dst[xx]){
dst[xx]=dst[x]+e[i].w;
if(!vst[xx]){
q.push(xx);
vst[xx]=1;
}
}
}
}
return;
}
//利用最短路求解时dst[j]有最大值
//利用最长路求解时dst[j]有最小值
int main(){
init();
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=0;i<n-2;i++){//插入有向边
insert(i+3,i,-(3*a[i+2]+2));
insert(i,i+3,3*a[i+2]);
}
//单独处理dst[2]即a1与a2的的情况
insert(2,0,-(2*a[1]+1));
insert(0,2,2*a[1]);
//单独处理dst[n]的情况
insert(n,n-2,-(2*a[n]+1));
insert(n-2,n,2*a[n]);
//每个值都需要大于等于1
for(int i=1;i<=n;i++){
insert(i-1,i,1);
}
spfa();
cout<<dst[1];
for(int i=2;i<=n;i++){
cout<<" ";
cout<<dst[i]-dst[i-1];
}
return 0;
}