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

 题目未给出只能移动到下一个装配线的条件:1->2->3->1 ,不能 1->2->1; 

使用dist数组记录到每个点的耗时,随便跑跑;

代码:

#include<bits/stdc++.h>
using namespace std;
#define piii pair<int,pair<int,int> > 
#define pii pair<int,int>
int n , m , T , k;
int s[4][12];
int p[4][12];
int dist[4][12];
int out[12];
void bfs(){
	map<pii,pii>mp;
    priority_queue<piii,vector<piii>,greater<piii> > q;
    memset(dist , 0x3f , sizeof dist);
    for(int i = 1 ; i <= n ; i ++){
    	dist[i][1] = s[i][1] + p[i][1];
        q.push({{dist[i][1]},{i,1}});
    }
	while(!q.empty()){
		int x = q.top().second.first;
		int y = q.top().second.second;
		q.pop();
		if(y == m)continue;
		for(int i = x ; i <= x+1 ; i ++){
            if(i == x){
				if(dist[i][y+1] <= dist[x][y] + s[i][y+1])continue;
				dist[i][y+1] = dist[x][y] + s[i][y+1];
				mp[{i,y+1}] = {x,y};
				q.push({{dist[i][y+1]},{i,y+1}});
			}else{
				if(i == n + 1)i = 1;
				
				if(dist[i][y+1] <= dist[x][y] + s[i][y+1] + p[i][y+1])break;
				
				dist[i][y+1] = dist[x][y] + s[i][y+1] + p[x][y+1];
				mp[{i,y+1}] = {x,y};
				q.push({{dist[i][y+1]},{i,y+1}});
				
				break;
			}
		}
	}
	int ans = INT_MAX;
	int ansx , ansy = m;
	for(int i = n ; i >= 1 ; i--){
		if(ans > dist[i][m] + out[i]){
			ans = dist[i][m] + out[i];
			ansx = i;
		}
	}
	cout << "Total Time " << ans << endl;
	vector<pii>v;
	while(ansx && ansy){
		v.push_back({ansx,ansy});
		ansx = mp[{ansx,ansy}].first;
		ansy --;
	}
	for(int i = v.size() - 1 ; i >= 0 ; i --){
		cout << v[i].first << " " << v[i].second << endl;
	}
}
int main(){
	while(cin >> n >> m){
		for(int i = 1 ; i <= n ; i ++)
	   		for(int j = 1 ; j <= m ; j ++)
	   			cin >> s[i][j];
		for(int i = 1 ; i <= n ; i ++)
			for(int j = 2 ; j <= m ; j ++)
				cin >> p[i][j];
		for(int i = 1 ; i <= n ; i ++)cin >> p[i][1];
		for(int i = 1 ; i <= n ; i ++)cin >> out[i];
	    bfs();
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值