NIOP 2015 推销员

先看数据,O(n)/O(nlogn)

很容易可以想出第k次的疲劳是在(k-1)次的基础上选择一个max(在已知最大点左边+此点的疲劳,(在已知最大点右边-已知最大点)*2+此点的疲劳)

于是很容易得出代码

#include<cmath>
#include<cstring>
#include<string>
#include<iostream>
#include<cstdio>
#include<vector>
#include<ctime>
#include<unordered_map>
#include<map>
#include<cstdlib>
#include<iomanip>
#include<queue>
#include<set>
#include<stack>
#include<algorithm>
#include<fstream>
using namespace std;
int s[1000000],tr[1000000],d[1000000],vis[1000000];
int main()
{
//	freopen("salesman.in","r",stdin);
//	freopen("salesman.out","w",stdout);
	int n;
	cin>>n;
	for(int i=1;i<=n;i++)
		cin>>s[i];
	int maxx=0,maxxp=0;
	for(int i=1;i<=n;i++)
	{
		cin>>tr[i];
		int u=s[i]*2+tr[i];
		if(u>maxx)
		{
			maxx=u;
			maxxp=i;	
		}
	}
	vis[maxxp]=1;
	cout<<maxx<<endl;
	d[1]=maxx;
	for(int i=2;i<=n;i++)
	{
		int v=0;
		for(int j=1;j<=n;j++)
		{
			if(vis[j])
				continue;
			if(j<maxxp)
				if(d[i-1]+tr[j]>d[i])
				{
					d[i]=d[i-1]+tr[j];
					v=j;
				}	
			if(j>maxxp)
				if(d[i-1]+(j-maxxp)*2+tr[j]>d[i])
				{
					d[i]=d[i-1]+(j-maxxp)*2+tr[j];
					v=j;
				}
		}	
		maxxp=max(maxxp,v);	
		vis[v]=1;
	}
	for(int i=2;i<=n;i++)
		cout<<d[i]<<endl;
	return 0;
}

 但这个代码时间复杂度超了

于是我们便把疲劳从大到小排序,再确定距离

每次确定距离时,要在前i个点与后(n-i)个点中确定一个最大值,

即在前i个点中,去点第i个点,再从(i+1)个点到n中选出一个距离+该点疲劳值最大值即可

为什么不选两个点及以上呢?

如果在后面选了一个点,那此时的距离已经达到最大,如果再选一个点的话只会减小疲劳值(已经排好序了),所以只选一个点就够

#include<cmath>
#include<cstring>
#include<string>
#include<iostream>
#include<cstdio>
#include<vector>
#include<ctime>
#include<unordered_map>
#include<map>
#include<cstdlib>
#include<iomanip>
#include<queue>
#include<set>
#include<stack>
#include<algorithm>
#include<fstream>
using namespace std;
struct node
{
	int s,tr;
}e[10000000];
int qian[10000000],hou[10000000],s[10000000];
int cmp(node a,node b)
{
	return a.tr>b.tr;
}
int main()
{
	int n;
	cin>>n;
	for(int i=1;i<=n;i++)
		cin>>e[i].s;
	for(int i=1;i<=n;i++)
		cin>>e[i].tr;
	sort(e+1,e+n+1,cmp);
	for(int i=1;i<=n;i++)
		s[i]=s[i-1]+e[i].tr;
	for(int i=1;i<=n;i++)
		qian[i]=max(e[i].s*2,qian[i-1]);
	for(int i=n;i>=1;i--)
		hou[i]=max(hou[i+1],e[i].s*2+e[i].tr);
	for(int i=1;i<=n;i++)
		cout<<max(qian[i]+s[i],hou[i]+s[i-1])<<endl;
	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值