1 条题解
-
0
市场摊位问题题解
题目分析
市场中有个现有摊位,新摊位需选择位置(现有摊位之后,)和价格,使得预期收入最大化。买家分两种方向行走(左→右、右→左),按规则选择价格最低的摊位(同价选最近)。需结合各值(经过个摊位后返回)的买家比例计算收入。
算法思路
-
价格候选生成:
最优价格通常出现在现有价格的邻近值(如略低于某摊位价格)。因此,生成所有现有价格的原值及原值减1作为候选价格,去重后排序。 -
枚举所有可能位置和价格:
遍历所有可能的新摊位位置()和候选价格,计算每个组合的预期收入。 -
收入计算(函数):
对每个位置和价格,模拟左右两个方向的买家行为:- 左→右方向:买家经过个摊位(),记录前个摊位的最低价格摊位。若新摊位是最低且最近,则累加对应的比例。
- 右→左方向:类似,买家从右向左经过个摊位,同样统计新摊位被选中的比例。
总收入为价格乘以总比例(左右各占50%)。
代码关键步骤解析
1. 输入处理与价格候选生成
- 候选价格生成逻辑:通过现有价格的原值及原值减1,覆盖可能的最优价格(如略低于某摊位价格以吸引买家)。
- 去重排序:确保候选价格唯一且有序,减少重复计算。
2. 收入计算函数
- 插入新摊位:将新摊位插入到位置(原摊位之后),调整数组顺序。
- 左→右统计:遍历前个摊位(),记录最低价格摊位。若新摊位是最低且最近,则累加对应的比例。
- 右→左统计:反向遍历,逻辑类似,注意值与的映射关系(如右→左经过个摊位对应)。
3. 枚举所有位置和价格,选择最优解
- 双重循环枚举:遍历所有可能的位置和候选价格。
- 最优解选择:优先收入最大;若收入相同,选最小;若相同,选最小。
示例验证(输入数据1)
输入:
5 37 34 34 35 33 10 20 30 30 10
- 候选价格:现有价格为、、、、,生成候选价格为、、、、、、、、、。去重排序后为、、、、、。
- 枚举位置(原摊位2之后),价格:
- 左→右方向:买家经过个摊位。插入新摊位后,价格数组为。前个摊位的最低价格摊位可能为新摊位(位置2),累加对应的比例。
- 右→左方向:反向遍历时,新摊位同样可能被选中,累加对应比例。
- 总收入为总比例,为最大收入。
标程
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<string> #include<queue> #include<algorithm> #include<vector> #include<stack> #include<list> #include<iostream> #include<map> using namespace std; #define inf 0x3f3f3f3f #define Max 110 int max(int a,int b) { return a>b?a:b; } int min(int a,int b) { return a<b?a:b; } int n; int pri[210],price[210],p[210],rat[210]; int count(int k,int p) { int i,tmp; for(i=0;i<k;i++) pri[i]=price[i]; for(i=k;i<n;i++) pri[i+1]=price[i]; pri[k]=p; int minx=inf,cnt=0; for(i=0;i<n;i++) { if(pri[i]<=minx) { minx=pri[i]; tmp=i; } if(tmp>k) break; if(tmp==k) cnt+=rat[i]; } minx=inf; for(i=n;i>0;i--) { if(pri[i]<=minx) { minx=pri[i]; tmp=i; } if(tmp<k) break; if(tmp==k) cnt+=rat[n-i]; } return p*cnt; } int main() { int i,j,cnt; scanf("%d",&n); for(i=0;i<n;i++) { scanf("%d",&price[i]); p[2*i]=price[i]-1;p[2*i+1]=price[i]; } for(i=0;i<n;i++) scanf("%d",&rat[i]); sort(p,p+2*n); cnt=1; for(i=1;i<2*n;i++) { if(p[i]>p[i-1]) p[cnt++]=p[i]; } int ans=0; int tmp; int pos=1; int recp=p[0]; for(i=1;i<n;i++) for(j=0;j<cnt;j++) { // printf("p %d\n",p[j]); tmp=count(i,p[j]); // printf("i %d j %d tmp %d\n",i,j,tmp); if(tmp>ans) { ans=tmp; pos=i; recp=p[j]; } } // printf("ans %d\n",ans); printf("%d %d\n",pos,recp); }
总结
本题通过枚举所有可能的位置和价格,结合买家行为模拟,计算预期收入,最终选择最优解。关键在于正确模拟买家选择逻辑(最低价格、同价选最近),并高效生成候选价格以覆盖可能的最优解。代码通过预处理候选价格和双重循环枚举,确保在合理复杂度内解决问题(时可行)。
-
- 1
信息
- ID
- 650
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 7
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者