1425:【例题4】加工生产调度
时间限制: 1000 ms 内存限制: 65536 KB
提交数: 2104 通过数: 544
【题目描述】
某工厂收到了 n 个产品的订单,这 n 个产品分别在 A、B 两个车间加工,并且必须先在 A 车间加工后才可以到 B 车间加工。
某个产品 i 在 A,B 两车间加工的时间分别为Ai,Bi。怎样安排这 n 个产品的加工顺序,才能使总的加工时间最短。
这里所说的加工时间是指:从开始加工第一个产品到最后所有的产品都已在 A,B 两车间加工完毕的时间。
【输入】
第一行仅—个数据 n ,表示产品的数量;
接下来 n 个数据是表示这 n 个产品在 A 车间加工各自所要的时间;
最后的 n 个数据是表示这 n 个产品在 B 车间加工各自所要的时间。
【输出】
第一行一个数据,表示最少的加工时间;
第二行是一种最小加工时间的加工顺序。
【输入样例】
5
3 5 8 7 10
6 2 1 4 9
【输出样例】
34
1 5 4 2 3
【提示】
对于100%的数据, 0 < n < 10000,所有数值皆为整数。
#include
#include
#include
#include
#define N 1005
using namespace std;
int ans[N],n,k,i,j,t,a[N];
int b[N],m[N],s[N];
void read(){
int i;
cin >> n;
for(i = 1; i <= n; i++)
cin >> a[i];
for(i = 1; i <= n; i++)
cin >> b[i];
}
void solve(){
for(i = 1; i <= n;i++)
{
m[i] = min(a[i],b[i]);
s[i] = i;
}
for(i = 1; i <= n-1;i++)//产品从小到大排序
for(j =i + 1; j<= n; j++)
if(m[i] > m[j])
{
swap(m[i],m[j]);
swap(s[i],s[j]);
}
k = 0,t = n + 1;
for(i = 1; i <= n;i++)//安排产品加工顺序
if(m[i] == a[s[i]])
{
k++;
ans[k] = s[i];
}
else{
t--;
ans[t] = s[i];
}
k = 0 ; t = 0;//k为A加工时间,t为B加工时间
for(i = 1; i <= n;i++){
k += a[ans[i]];
if(t < k) t = k;
t += b[ans[i]];
}
cout << t << endl;
for(i = 1; i <= n; i++)
cout << ans[i] << " ";
cout << endl;
}
int main(){
read();
solve();
return 0;
}
1426:【例题5】智力大冲浪
【题目描述】
小伟报名参加中央电视台的智力大冲浪节目。本次挑战赛吸引了众多参赛者,主持人为了表彰大家的勇气,先奖励每个参赛者m元。先不要太高兴!因为这些钱还不一定都是你的。接下来主持人宣布了比赛规则: 首先,比赛时间分为n个时段(n≤500),它又给出了很多小游戏,每个小游戏都必须在规定期限ti前完成(1≤ti≤n)。如果一个游戏没能在规定期限前完成,则要从奖励费m元中扣去一部分钱wi,wi为自然数,不同的游戏扣去的钱是不一样的。当然,每个游戏本身都很简单,保证每个参赛者都能在一个时段内完成,而且都必须从整时段开始。主持人只是想考考每个参赛者如何安排组织自己做游戏的顺序。作为参赛者,小伟很想赢得冠军,当然更想赢取最多的钱! 注意:比赛绝对不会让参赛者赔钱!
【输入】
输入共4行。
第一行为m,表示一开始奖励给每位参赛者的钱;
第二行为n,表示有n个小游戏; 第三行有n个数,分别表示游戏1~n的规定完成期限;
第四行有n个数,分别表示游戏1~n不能在规定期限前完成的扣款数。
【输出】
仅1行。表示小伟能赢取最多的钱。
【输入样例】
10000
7
4 2 4 3 1 4 6
70 60 50 40 30 20 10
【输出样例】
9950
【提示】
数据范围及提示:
n≤500,1≤ti≤n
#include
#include
#include
#include
using namespace std;
const int MAXN = 505;
struct edge {
int t, w;
edge() {}
edge(int t, int w) : t(t), w(w) {}
bool operator < (const edge &s) const {
return w > s.w;
}
}p[MAXN];
bool vis[MAXN];
int main() {
int n, m;
scanf("%d%d", &m, &n);
for (int i = 0; i < n; i++)
scanf("%d", &p[i].t);
for (int i = 0; i < n; i++)
scanf("%d", &p[i].w);
sort(p, p + n);
for (int i = 0; i < n; i++) {
int r = p[i].t;
while (r > 0 && vis[r])
r--;
if (r > 0) vis[r] = true;
else m -= p[i].w;
}
printf("%d\n", m);
return 0;
}
1430:家庭作业
【题目描述】
老师在开学第一天就把所有作业都布置了,每个作业如果在规定的时间内交上来的话才有学分。每个作业的截止日期和学分可能是不同的。例如如果一个作业学分为10,要求在6天内交,那么要想拿到这10学分,就必须在第6天结束前交。
每个作业的完成时间都是只有一天。例如,假设有7次作业的学分和完成时间如下:
作业号 1 2 3 4 5 6 7
期限 1 1 3 3 2 2 6
学分 6 7 2 1 4 5 1
最多可以获得15学分,其中一个完成作业的次序为2,6,3,1,7,5,4,注意可能d还有其他方法。
你的任务就是找到一个完成作业的顺序获得最大学分。
【输入】
第一行一个整数N,表示作业的数量。
接下来N行,每行包括两个整数,第一个整数表示作业的完成期限,第二个数表示该作业的学分。
【输出】
输出一个整数表示可以获得的最大学分。保证答案不超过longint范围。
【输入样例】
7
1 6
1 7
3 2
3 1
2 4
2 5
6 1
【输出样例】
15
#include
#include
#include
#include
#include
#include
#include
#include
#define N 1000001
using namespace std;
int n,dislike;
long long ans;
bool vis[N],f[N];
struct node
{
int t,w;
}work[N];
bool cmp(node x,node y)
{
return x.w > y.w ;
}
bool pd(int x)
{
for(int i = work[x].t ;i >= 1;i--)
{
if(vis[i] == 0)
{
vis[i] = 1;
return 1;
}
}
dislike = work[x].t ; //不可以继续安排作业了
return 0;
}
int main()
{
scanf("%d",&n);
for(int i = 1;i <= n;i++)
scanf("%d%d",&work[i].t ,&work[i].w );
sort(work+1,work+n+1,cmp);
memset(vis,0,sizeof(vis));
for(int i = 1;i <= n;i++)
{
if(work[i].t < dislike) continue; //在1~dislike区间里都不可以安排作业了
if(pd(i)) ans += work[i].w ;
}
printf("%ld",ans);
return 0;
}