
咋一看,这一题可以用贪心做,但是,时间复杂度是O(n*n),只能过60%的数据。
【贪心算法】(超时,60分)
#include<cstdio>
#include<cstring>
using namespace std;
int n,i,ans,sum,o,j,maxy=0,p;
unsigned long long a[100003],b[100003],maxx=0;
bool bo[100003];
int main()
{
freopen("salesman.in","r",stdin);
freopen("salesman.out","w",stdout);
scanf("%d",&n);
for(i=1;i<=n;i++) scanf("%d",&a[i]);
for(i=1;i<=n;i++) scanf("%d",&b[i]);
p=0;
memset(bo,1,sizeof(bo));
for(i=1;i<=n;i++)
{
int maxo=0;
for(j=1;j<=n;j++)
if(bo[j]==1)
{
if(a[j]>p) p=a[j];
if((p*2+b[j])>maxo) { maxo=p*2+b[j]; o=j;}
}
if(p<a[o]) p=a[o];
bo[o]=0;
if(a[o]>maxy) maxy=a[o];
maxx+=b[o];
printf("%lld\n",maxx+(maxy*2));
}
return 0;
}
#include<cstring>
using namespace std;
int n,i,ans,sum,o,j,maxy=0,p;
unsigned long long a[100003],b[100003],maxx=0;
bool bo[100003];
int main()
{
freopen("salesman.in","r",stdin);
freopen("salesman.out","w",stdout);
scanf("%d",&n);
for(i=1;i<=n;i++) scanf("%d",&a[i]);
for(i=1;i<=n;i++) scanf("%d",&b[i]);
p=0;
memset(bo,1,sizeof(bo));
for(i=1;i<=n;i++)
{
int maxo=0;
for(j=1;j<=n;j++)
if(bo[j]==1)
{
if(a[j]>p) p=a[j];
if((p*2+b[j])>maxo) { maxo=p*2+b[j]; o=j;}
}
if(p<a[o]) p=a[o];
bo[o]=0;
if(a[o]>maxy) maxy=a[o];
maxx+=b[o];
printf("%lld\n",maxx+(maxy*2));
}
return 0;
}
下面是正解:
第一步:找出所有中的最大值,记录下标k
第二步:在k的前面找ai的最大值与下标记录,在k的后面找ai+di*2的最大值与下标记录(预处理)
第三步:比较二者选较大值,如果值在k的后面则将k的值改变
第四步:打印当前答案,转(2),循环n-1次。
第二步:在k的前面找ai的最大值与下标记录,在k的后面找ai+di*2的最大值与下标记录(预处理)
第三步:比较二者选较大值,如果值在k的后面则将k的值改变
第四步:打印当前答案,转(2),循环n-1次。
【正解程序】
#include<cstdio>
using namespace std;
int n,i,j,a[100010],b[100010],c[100010],t[100010];
int max,k1,k2,k,i1;
int main()
{
freopen("salesman.in","r",stdin);
freopen("salesman.out","w",stdout);
scanf("%d",&n);
for(i=0;i<n;i++)
scanf("%d",&a[i]);
for(i=0;i<n;i++)
scanf("%d",&b[i]);
max=k=-1;
for(i=0;i<n;i++)
if((a[i]*2)+b[i]>max)
{
max=(a[i]*2)+b[i];
k=i;
}
printf("%d\n",max);
c[n-1]=n-1;
for(i=n-2;i>=0;i--)
{
if(a[i+1]*2+b[i+1]<a[i]*2+b[i])
c[i]=i;
else c[i]=c[i+1];
}
for(i=0;i<k;i++) t[b[i]]++;
for(i=1;i<n;i++)
{
i1=k1=-1;
if(k<n-1)
{
i1=c[k+1];
k1=(a[i1]-a[k])*2+b[i1];
}
for(j=1000;j>=1;j--)
if(t[j]>0)
{
k2=j;
--t[j];
break;
}
if(k1>k2)
{
max+=k1;
k=i1;
printf("%d\n",max);
}
else
{
max+=k2;
printf("%d\n",max);
}
}
return 0;
}
#include<cstdio>
using namespace std;
int n,i,j,a[100010],b[100010],c[100010],t[100010];
int max,k1,k2,k,i1;
int main()
{
freopen("salesman.in","r",stdin);
freopen("salesman.out","w",stdout);
scanf("%d",&n);
for(i=0;i<n;i++)
scanf("%d",&a[i]);
for(i=0;i<n;i++)
scanf("%d",&b[i]);
max=k=-1;
for(i=0;i<n;i++)
if((a[i]*2)+b[i]>max)
{
max=(a[i]*2)+b[i];
k=i;
}
printf("%d\n",max);
c[n-1]=n-1;
for(i=n-2;i>=0;i--)
{
if(a[i+1]*2+b[i+1]<a[i]*2+b[i])
c[i]=i;
else c[i]=c[i+1];
}
for(i=0;i<k;i++) t[b[i]]++;
for(i=1;i<n;i++)
{
i1=k1=-1;
if(k<n-1)
{
i1=c[k+1];
k1=(a[i1]-a[k])*2+b[i1];
}
for(j=1000;j>=1;j--)
if(t[j]>0)
{
k2=j;
--t[j];
break;
}
if(k1>k2)
{
max+=k1;
k=i1;
printf("%d\n",max);
}
else
{
max+=k2;
printf("%d\n",max);
}
}
return 0;
}