PTA 装配线与工作站

某汽⻋公司在有多条装配线的⼯⼚内⽣产汽⻋,⼀个汽⻋底盘在进⼊每⼀条装配线后,在每个⼯作站会在汽⻋底盘上安装不同的部件,最后完成的汽⻋从装配线的末端离开。
每⼀条装配线上都有 n 个⼯作站,装配线i的第 j 个⼯作站 用S(i,j)表示, 在两条装配线相同位置的⼯作站执⾏相同的功能,但由于⼯作站是在不同的时间建造的,并且采⽤了不同的技术,因此,每个⼯作站上完成装配所需要的时间也不相同。
正常情况下,底盘从同⼀条装配线的上⼀个⼯作站移到下⼀个⼯作站所花费的时间可以忽略,是遇到紧急订单时也会将未完成的底盘从⼀条装配线的⼀个⼯作站移到另⼀条装配线的下⼀个⼯作站,但从某装配线移⾛到另一个装配线的下一工作站也需要花费一定时间,此外,底盘进⼊装配线 i 需要的时间为 e(i),离开装配线 i 需要的时间是 x(i)。
请选择在哪些装配线内的⼯作站进行装配,以使汽⻋通过⼯⼚的总时间最⼩。
如下图所示, 最快的时间是选择装配线1的 1、3和 6 号⼯作站以及装配线 2 的 2、4 和 5 号⼯作站,最短的通过时间为38。

输入格式:

第一行是装配线数量LINES和工作站数量STATIONS,用空格符间隔。

接下来LINES行是每个装配线上工作站的装配时间。

接下来LINES行是从当前装配线移到其它装配线下一个工作站的移动时间。注意最后一个工作站没有移动时间。

接下来一行是进入各条装配线的时间e[i]。

接下一行是退出各装配线的时间x[i]。

输出格式:

第一行输出总的装配时间。

接下来按照顺序输出装配过程,格式如下:

装配线 工作站

输入样例:

在这里给出一组输入。例如:

2 6
7 9 3 4 8 4
8 5 6 4 5 7
2 3 1 3 4 
2 1 2 2 1
2 4
3 2

输出样例:

在这里给出相应的输出。例如:

Total Time 38
1 1
2 2
1 3
2 4
2 5
1 6

思路:经过严谨专业的骗分后得出,这题数据量很小,那直接电风扇(DFS)暴力穷举也不会超时,直接一个for列举尝试每条线的可能,记录下最小时间就行。虽然但是,我还是加了点小剪枝(详见代码)

坑点:1.在当前x装配线下只能前往x,x+1的装配线,最后一条装配线可以跳到第一条。

        2.到最后一个工作站之后要加上当前装配线的出线时间然后算答案,不能再移动装配线。

AC代码

#include<bits/stdc++.h>
using namespace std;
int n,m;
struct node{//用来存每一条线上每个站的制造时间和换线时间,还有出入时间 
	int in_time;
	int out_time;
	int make_time[10086];
	int turn_time[10086];
}lst[10086];
vector<int>anss;
int tmp = 0x3f3f3f3f;//耗时先初始化成无穷大 
void dfs(int s,int x,int sum,vector<int> v){
//s表示当前步骤,x表示当前在哪条线,sum表示走到这步的耗时,v存储路线 
	if(sum>tmp && s<m){
		return ;//小剪枝,如果当前还没完成就已经比最小答案大了就不必跑了 
	}
	if(s == m+1){//跑完了 
		if(sum<tmp){
			tmp = sum;
			anss = v;
		}
		return ;
	}
	if(x==n){//如果当前是最后一个装配线那就只能去x和1 
		int tm  = sum;
		if(s==m){
			tm += lst[x].make_time[s];
			tm += lst[x].out_time;
		}else{
			tm += lst[x].make_time[s];
		}
		vector<int>vvv;
		vvv = v;
		vvv.push_back(x);
		dfs(s+1,x,tm,vvv);
		tm += lst[x].turn_time[s];
		dfs(s+1,1,tm,vvv);
	}else{//如果不是最后一条,就分别尝试x和x+1 
		for(int i=x;i<=x+1;i++){
			int tm = sum;
			if(s==m){
				tm += lst[x].make_time[s];
				tm += lst[x].out_time;
			}else{
				tm += lst[x].make_time[s];
				if(i!=x){
					tm += lst[x].turn_time[s];
				}
			}
			//tm 计算 
			vector<int>vvv;
			vvv = v;
			vvv.push_back(x);
			dfs(s+1,i,tm,vvv);
		}
	}
}
int main(){
	cin>>n>>m;//输入 
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			int a;
			cin>>a;
			lst[i].make_time[j]=a;
		}
	}//输入 
	for(int i=1;i<=n;i++){
		for(int j=1;j<m;j++){
			int a;
			cin>>a;
			lst[i].turn_time[j]=a;
		}
	}//还是输入 
	for(int i=1;i<=n;i++){
		int a;
		cin>>a;
		lst[i].in_time =a;
	}//怎么还是输入啊啊 啊 
	for(int i=1;i<=n;i++){
		int a;
		cin>>a;
		lst[i].out_time =a;
	}
	for(int i=1;i<=n;i++){
		vector<int>vv;//分别尝试从每条线路开始,暴力枚举 
		dfs(1,i,lst[i].in_time,vv);
	}
	//输出 
	cout<<"Total Time "<<tmp<<endl;
	int cnt=1;
	for(auto it:anss){
		cout<<it<<" "<<cnt<<endl;
		cnt++;
	}
	return 0;
} 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值