ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[洛谷P3584] POI2015 LAS

2020-09-24 23:31:22  阅读:250  来源: 互联网

标签:洛谷 食物 更优 左边 选择 P3584 && 转移 LAS


问题描述

圆桌上摆放着n份食物,围成一圈,第i份食物所含热量为c[i]。 相邻两份食物之间坐着一个人,共有n个人。每个人有两种选择,吃自己左边或者右边的食物。如果两个人选择了同一份食物,这两个人会平分这份食物,每人获得一半的热量。 假如某个人改变自己的选择后(其他n-1个人的选择不变),可以使自己获得比原先更多的热量,那么这个人会不满意。 请你给每个人指定应该吃哪一份食物,使得所有人都能够满意。

输入格式

第一行一个整数n(2<=n<=1000000),表示食物的数量(即人数)。食物和人都从1~n编号。第二行包含n个整数c[1],c[2],…,c[n]。假设第i个人(1<=i<n)左边是第i份食物,右边是第i+1份食物;而第n个人左边是第n份食物,右边是第1份食物。

输出格式

如果不存在这样的方案,仅输出一行NIE。如果存在这样的方案,输出一行共n个整数,第i个整数表示第i个人选择的食物的编号。如果有多组这样的方案,输出任意一个即可。

样例输入

5
5 3 7 2 9

样例输出

2 3 3 5 1

解析

设 \(f_{i,0/1/2/3}\) 表示当前在第 \(i\) 个食物,\(0\) 表示没有人选这个食物;\(1\) 表示左边的人选择;\(2\) 表示右边的人选择;\(3\) 表示两个人都选,而 \(f\) 中记录的是当前状态下前一个食物的转移状态 \((0,1,2,3)\)。转移时我们只需要考虑食物左边的人的选择情况,运用贪心的思想进行转移:决策点的优先程度取决于这个决策点带来的收益。

  • 不选择第 \(i\) 个食物,说明左边的人选右边一定更优。讨论一下 \(a_{i-1}\) 与 \(a_i\) 的关系,如果 \(a_{i-1}>a_i\),说明左边的人直接选择 \(i-1\) 会更优,会从 \(f_{i-1,2}\) 转移;否则,如果 \(a_{i-1}/2>a_{i}\) ,说明即使左边的人和另一个人共享 \(a_{i-1}\) 也比选 \(i\) 更优,会从 \(f_{i-1,3}\) 转移过来。
  • 左边的人选择第 \(i\) 个食物。如果 \(a_{i-1}\le a_i\) ,说明即使左边的人独占 \(i-1\) 也不如选择 \(i\) ,会从 \(f_{i-1,0}\) 转移过来;如果 \(a_{i-1}/2\le a_i\) ,说明共享 \(i-1\) 不如独占 \(i\) ,会从 \(f_{i-1,1}\) 转移过来。
  • 右边的人选择第 \(i\) 个食物。如果 \(a_{i-1}\ge a_i/2\) ,说明左边的人独占 \(i-1\) 更优,会从 \(f_{i-1,1}\) 转移过来;如果 \(a_{i-1}/2\ge a_i/2\) ,说明共享 \(i-1\) 会更优,从 \(f_{i-1,3}\) 转移。
  • 共享第 \(i\) 个食物。如果 \(a_{i-1}\le a_{i-1}/2\) ,说明左边的人独占 \(i-1\) 也没有分享 \(i\) 更优,从 \(f_{i-1,0}\) 转移。如果 \(a_{i-1}/2\le a_{i}/2\) ,说明共享 \(i-1\) 还不如共享 \(i\) ,从 \(f_{i-1,1}\) 转移。

由于是环,所以需要先枚举最后第一个食物是什么状态,然后DP完第 \(n\) 个食物之后再回来更新第 \(1\) 个,看是不是合法。然后从后往前确定食物的归属即可。

代码

#include <iostream>
#include <cstdio>
#include <cstring>
#define N 1000002
using namespace std;
int n,i,j,a[N],f[N][4],g[N],ans[N];
bool flag;
int read()
{
	char c=getchar();
	int w=0;
	while(c<'0'||c>'9') c=getchar();
	while(c<='9'&&c>='0'){
		w=w*10+c-'0';
		c=getchar();
	}
	return w;
}
int main()
{
	n=read();
	for(i=1;i<=n;i++) a[i]=read();
	for(j=0;j<=3;j++){
		memset(f,-1,sizeof(f));
		f[1][j]=4;
		for(i=2;i<=n;i++){
			if(a[i-1]>=a[i]&&f[i-1][2]!=-1) f[i][0]=2;
			else if(a[i-1]>=a[i]*2&&f[i-1][3]!=-1) f[i][0]=3;
			if(a[i-1]<=a[i]&&f[i-1][0]!=-1) f[i][1]=0;
			else if(a[i-1]<=a[i]*2&&f[i-1][1]!=-1) f[i][1]=1;
			if(a[i-1]*2>=a[i]&&f[i-1][2]!=-1) f[i][2]=2;
			else if(a[i-1]>=a[i]&&f[i-1][3]!=-1) f[i][2]=3;
			if(a[i-1]*2<=a[i]&&f[i-1][0]!=-1) f[i][3]=0;
			else if(a[i-1]<=a[i]&&f[i-1][1]!=-1) f[i][3]=1;
		}
		if(a[n]>=a[1]&&f[n][2]!=-1) f[1][0]=2;
		else if(a[n]>=a[1]*2&&f[n][3]!=-1) f[1][0]=3;
		if(a[n]<=a[1]&&f[n][0]!=-1) f[1][1]=0;
		else if(a[n]<=a[1]*2&&f[n][1]!=-1) f[1][1]=1;
		if(a[n]*2>=a[1]&&f[n][2]!=-1) f[1][2]=2;
		else if(a[n]>=a[1]&&f[n][3]!=-1) f[1][2]=3;
		if(a[n]*2<=a[1]&&f[n][0]!=-1) f[1][3]=0;
		else if(a[n]<=a[1]&&f[n][1]!=-1) f[1][3]=1;
		if(f[1][j]!=4){
			flag=1;
			g[n]=f[1][j];
			for(i=n;i>=1;i--) g[i-1]=f[i][g[i]];
			for(i=1;i<=n;i++){
				if(g[i]==0||g[i]==1) ans[i]=i%n+1;
				else ans[i]=i;
			}
			for(i=1;i<=n;i++) printf("%d ",ans[i]);
			puts("");
			break;
		}
	}
	if(!flag) puts("NIE");
	return 0;
}

标签:洛谷,食物,更优,左边,选择,P3584,&&,转移,LAS
来源: https://www.cnblogs.com/LSlzf/p/13727355.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有