心路历程(如果你没有时间请直接跳到下一板块(。・_・)/~~~)
针对于这道题,一开始博主并不知道也没有用所谓的Johnson算法;
① 当博主发现这是一道贪心算法的时候,也没有很直接的思路和策略,所以博主就用了最直接的a车间的工作时间除以b车间的工作时间 (水过了44分的数据)
bool mycmp(number x,number y)
{
return x.c<y.c;
}
for(int i=1;i<=n;i++)
{
num[i].b=read();
num[i].c=(num[i].a*1.0)/(num[i].b*1.0);//这个就是博主的鬼畜求商
}
sort(num+1,num+n+1,mycmp);
//这些是部分代码
//下面是模拟求和
ans+=num[1].a;
for(int i=1;i<n;i++)
{
ans+=num[i].b;
int tot=num[i+1].a-num[i].b;
ans+=tot;
}
ans+=num[n].b;
printf("%lld\n",ans);
② 当博主发现并不能解决这道题的时候,又思考了好长时间(或许是博主太弱了),博主发现实际上a车间的工作是连续不停的!!于是乎,博主就
想到了用a车间的总时间加上b车间的最小值,因为在a车间完成之后,b车间应该是会有剩余一件的物品,此时若使b车间最后加工的一件物品的工作时间最小,那么不就是总时间最小了吗!!!!!! (呵呵,天真=_=)(然后就水过了76分)
for(int i=1;i<=n;i++)
{
num[i].id=i;
num[i].a=read();
sum1+=num[i].a;//sum1和sum2在这里分别是a车间的工作总和和b车间的工作总和
a1=min(a1,num[i].a);//a1,b1分别是a车间的最小的工作时间和b车间的最小工作时间
}
for(int i=1;i<=n;i++)
{
num[i].b=read();
num[i].c=(num[i].a*1.0)/(num[i].b*1.0);//依旧是上面的鬼畜算法
b1=min(b1,num[i].b);
sum2+=num[i].b;
}
sort(num+1,num+1+n,mycmp);
if(sum1>sum2)
{
ans+=sum1;
ans+=b1;
}
else
{
ans+=sum2;
ans+=a1;
}
printf("%lld\n",ans);
现在博主想到自己之前的种种做法发现这其中都是有问题的
1.首先先说贪心策略(就是内个鬼畜算法的排列方式)是博主灵光一现 瞎诌出来的,缺乏证明(但是不得不说是可以水 分的 );
2.模拟的时候就是根本没有一个依据啥的就是在瞎搞;
这是正文!
针对于A,B车间,A车间是一直在运作,而B车间中间是有空缺的,因为有时候,B车间会因为等待A车间的第一次生产而需要更多的时间。
那么这个时候,就可以想一下,应该如何排序的呢?使得B车间中的空闲时间最少。
可以自己稍微思考一下,如果不会就看一下下面的正确策略。
①策略:让在A车间中花费时间最少的在前面(这样子的话,就会让B最先开始开工,那么一开始等待的时间就会较少一些),让在B车间中工作时间最少的放在最后(那么就是在A车间工作结束后,B车间工作的时间最少),这样的话就会很好的处理到了A,B车间的空闲时间最少,从而得到了最少的工作时间。
部分处理代码如下
struct number
{
int id,a,b,m;
};
number num1[1010];//这里面保存的是原始的排列顺序
number num2[1010];//这里面保存的是排列后的顺序
for(int i=1;i<=n;i++)
{
num1[i].b=read();
num1[i].m=min(num1[i].a,num1[i].b);//先找到第i件中的A,B车间的最小的
}
sort(num1+1,num1+1+n,mycmp);
int l=0,r=n+1;
for(int i=1;i<=n;i++)
{
if(num1[i].m==num1[i].a)//此时最小值是A车间中的,应该放在队列的前面
num2[++l]=num1[i];
else
num2[--r]=num1[i];//同理可得此时最小值是B车间中的,应该放在队列的后面
}
②模拟求和
我觉得对于我来说,上面的排序并不是很大的问题,而真正的难题是最后收尾的求和
在这里以B车间为标准,(即若是求出来了B车间中的工作时间,那么就是这个过程中的工作时间)
见下图(针对于样例来说):
所以可以整体考虑,当A车间的整体的值大于B车间的值是,B车间的工作时间就要变成A车间的工作时间。
见部分代码:
for(int i=1;i<=n;i++)
{
sum1+=num2[i].a;
sum2=max(sum1,sum2)+num2[i].b;
}
见全部代码如下:
#include<bits/stdc++.h>
using namespace std;
int n;
long long sum1=0,sum2=0;
struct number
{
int id,a,b,m;
};
number num1[1010];
number num2[1010];
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
return x*f;
}
bool mycmp(number x,number y)
{
return x.m<y.m;
}
int main()
{
//freopen("1.in","r",stdin);
n=read();
for(int i=1;i<=n;i++)
{
num1[i].id=i;
num1[i].a=read();
}
for(int i=1;i<=n;i++)
{
num1[i].b=read();
num1[i].m=min(num1[i].a,num1[i].b);
}
sort(num1+1,num1+1+n,mycmp);
int l=0,r=n+1;
for(int i=1;i<=n;i++)
{
if(num1[i].m==num1[i].a)//此时应该放在队列的前面
num2[++l]=num1[i];
else
num2[--r]=num1[i];
}
for(int i=1;i<=n;i++)
{
sum1+=num2[i].a;
sum2=max(sum1,sum2)+num2[i].b;
}
printf("%lld\n",sum2);
for(int i=1;i<=n;i++)
{
printf("%d ",num2[i].id);
}
return 0;
}
其实,上面的心路历程我也不知道写了些什么……
总之,2019肯定会更好的呀!!!!