OJ算法分析题库(2)

P1476 加工生产调度

【实验】贪心算法之流水作业调度问题(分析

P1748 a+b+c+d==0

P1750 求逆序对

P1746 求解查找最后一个数小于等于指定数的元素问题

P1477 部分背包问题(分析

算法分析:

算法大致的思路就是通过四个数组分别存储每次输入的数值内容。然后通过分组循环,四个数分两组,a和b一组进行一对多依次加法存到数组中,保证每个a组的数都和b组中的所有数进行过了加法运算。c和d也是一样的方式。

两个数组ab和cd运算完毕以后,进行排序。排序完成以后接下来通过对ab数组的值进行依次循环,然后每次都会cd数组也进行循环判断,找到ab+cd=0的情况的个数。为了应对数值相同的情况,这里用到了upper_bound和lower_bound两个函数进行运算,具体原理读者可以自行分析。总之经过如上的运算,最终可以得到相应的个数。

这里是相应的算法。来源于网络,算法非原创,分析为原创,仅供学习使用,如果侵权请告知删除

/*
 * @Description: To iterate is human, to recurse divine.
 * @Autor: Recursion
 * @Date: 2022-03-23 09:44:28
 * @LastEditTime: 2022-03-23 12:03:40
 */
#include<bits/stdc++.h>
using namespace std;
int T,n,sum;
int a[10000],b[10000],c[10000],d[10000];
int ab[200000001],cd[200000001];
// int a[10000][10000];
 
// void read()
// {
//     for(int i = 1;i <= n;i ++)
//         for(int j = 1;j <= 4;j ++)
//             cin >> a[i][j];
// }
// void dfs(int x)
// {
//     if(x == 4 + 1){
//         if(sum == 0)
//             ans++;
//         return;
//     }
//     for(int i = 1;i <= n;i ++){
//         sum += a[i][x];
//         dfs(x + 1);
//         sum -= a[i][x];
//     }
 
// }
 
// int main()
// {
//     cin >> T;
//     while(T--){
//         cin >> n;
//         read();
//         dfs(1);
//         cout << ans << endl;
//     }
// }
 
void read()
{
    for(int i = 0;i < n;i ++)
        cin >> a[i] >> b[i] >> c[i] >> d[i];
}
 
void solve()
{
    for(int i = 0;i < n;i ++)
        for(int j = 0;j < n;j ++){
            ab[i*n + j] = a[i] + b[j];
            cd[i*n + j] = c[i] + d[j];
        }
    sort(ab,ab + n*n);
    sort(cd,cd + n*n);
    long long int ans = 0;
    for(int i = 0;i < n*n;i ++){
        int temp = -ab[i];
        ans += upper_bound(cd,cd + n*n, temp) - lower_bound(cd,cd + n*n,temp);
    }
    /*
    upper_bound(first, last, val) 寻找在数组或容器的[first,last)范围第一个大于val的元素位置
    lower_bound(first, last, val)寻找在数组或容器的[first,last)范围第一个大于等于val的元素位置
    使用时必须为有序的数组或容器
    相减得到相等个数
    
    lower_bound:
    功能:查找非递减序列[first,last) 内第一个大于或等于某个元素的位置。
    返回值:如果找到返回找到元素的地址否则返回last的地址。(这样不注意的话会越界,小心)
    用法:int t=lower_bound(a+l,a+r,key)-a;(a是数组)。
    upper_bound:
    功能:查找非递减序列[first,last) 内第一个大于某个元素的位置。
    返回值:如果找到返回找到元素的地址否则返回last的地址。(同样这样不注意的话会越界,小心)
    
    用法:int t=upper_bound(a+l,a+r,key)-a;(a是数组)。
    */
    cout << ans << endl;
}
 
int main()
{
    int t;
    cin >> t;
    while(t--){
        cin >> n;
        read();
        solve();
    }
}

 这题就是一道比较简单的求逆序数的问题。

算法1:暴力比较法 两次循环比较 时间复杂度是n平方 时间浪费很多

#include<iostream>
using namespace std;
int numbers=0;
void getresult(int a[],int start,int n){
	if(start==n-1)
		return;
	for(int i=start+1;i<=n-1;i++){
		if(a[start]>a[i])
			numbers++;
	}
}
int main(){
	int n;cin>>n;int a[n];
	for(int i=0;i<n;i++)
		cin>>a[i];
	for(int i=0;i<=n-2;i++)
		getresult(a,i,n);
	cout<<numbers<<endl;
	return 0;
}

 这里为了节省时间 我们不妨考虑借助二路归并排序的思想 进行分治法的求逆序数

(但是oj判断Runtime error 不清楚为什么 待解决)

#include<iostream>
int numbers=0;
using namespace std;
void getnumber(int a[],int low,int mid,int high){
	int i=low;int j=mid+1;int k=0;int tmp[100];
	while(i<=mid && j<=high){
		if(a[i]>a[j]){
			numbers+=mid-i+1;
			tmp[k++]=a[j++];
		}	
		else tmp[k++]=a[i++];
	}
	while(i<=mid) tmp[k++]=a[i++];
	while(j<=high) tmp[k++]=a[j++];
	for(int k1=0;k1<k;k1++)
		a[low+k1]=tmp[k1];
}
void Merge_sort(int a[],int low,int high){
	if(low<high){
		int mid=(low+high)/2;
		Merge_sort(a,low,mid);
		Merge_sort(a,mid+1,high);
		getnumber(a,low,mid,high);
	}	
}
int main(){
	int n;cin>>n;
	int a[n];
	for(int i=0;i<n;i++)
		cin>>a[i];
	Merge_sort(a,0,n-1);
	cout<<numbers<<endl;
	return 0;
}

这里再提供一个通过oj判断的算法

#include <bits/stdc++.h>
using namespace std;

#define ll long long
#define lson l,mid,tree[rt].l
#define rson mid+1,r,tree[rt].r
#define ls tree[rt].l
#define rs tree[rt].r

const int mac=5e5+10;
const int inf=1e9+5;

struct node
{
    int l,r,sum;
}tree[mac*32];
int sz=1;//动态分配的点的最大编号

ll query(int l,int r,int rt,int L,int R)
{
    ll ans=0;
    if (l>=L && r<=R){
        return tree[rt].sum;
    }
    int mid=(l+r)>>1;
    if (mid>=L) ans+=query(lson,L,R);
    if (mid<R) ans+=query(rson,L,R);
    return ans;
}

void update(int l,int r,int &rt,int pos)
{
    if (!rt) rt = ++sz;//如果说这个节点不存在,我们就将节点数+1,当前节点为最大最大节点,和主席树有点类似,而这也是动态开点的核心
    if (l==r) {
        tree[rt].sum++;
        return;
    }
    int mid=(l+r)>>1;
    if (mid>=pos) update(lson,pos);//注意这里传进去的rt是左儿子的编号
    else update(rson,pos);
    tree[rt].sum=tree[ls].sum+tree[rs].sum;
}

int main()
{
    int n;
    scanf ("%d",&n);
    ll ans=0;
    int root=1;
    for (int i=1; i<=n; i++){
        int x;
        scanf ("%d",&x);
        ans+=query(1,inf,1,x+1,inf);
        update(1,inf,root,x);
    }
    printf ("%lld\n",ans);
    return 0;
}

 借助二分查找排序的思路进行递归比较 这样时间复杂度低 浪费的时间少

#include<bits/stdc++.h>
using namespace std;
void functions(int a[],int b[],int n,int m){
	for(int i=0;i<m;i++){
		int l=0,r=n-1,mid;
		while(l<=r){
			mid=(l+r)/2;
			if(a[mid]<=b[i]) l=mid+1;
			else r=mid-1;
		}
		b[i]=a[r];
	}
}
int main(){
	int n,m,i;cin>>n>>m;int a[n],b[m];
	for(i=0;i<n;i++) cin>>a[i];
	for(i=0;i<m;i++) cin>>b[i];
	functions(a,b,n,m);
	for(i=0;i<m;i++) cout<<b[i]<<endl; return 0;
}

自行编写:

#include<bits/stdc++.h>
using namespace std;
void fun(int a[],int b[],int n,int m){
	for(int i=0;i<m;i++){  //外圈大循环 用于依次处理相应的待处理数据 b[i]即表示待测试数据 
		if(b[i]>=a[n-1]){ b[i]=a[n-1]; continue; }
		if(b[i]<a[0]) { b[i]=-1; continue; }
		if(b[i]==a[0]) { b[i]=a[0]; continue;}
		int left=0,right=n-1,mid;
		while(left<=right){
			mid=(right+left)/2;
			if(a[mid]<=b[i]) left=mid+1;
			else right=mid-1;
		} 
		b[i]=a[right];
	}
}
int main(){
	int n,m; cin>>n>>m; int a[n],b[m];
	for(int i=0;i<n;i++) cin>>a[i];
	for(int j=0;j<m;j++) cin>>b[j];
	fun(a,b,n,m); for(int i=0;i<m;i++) cout<<b[i]<<endl; return 0;
}

 模型是经典的背包可分割问题 我们采用贪心算法即可完成

#include<bits/stdc++.h>
using namespace std;
struct NodeType{
	double weight;double value;double p;
	bool operator<(const NodeType &s) const{
		return p>s.p;
	}
};
int main(){
	int N,T,i;cin>>N>>T;double value=0.0;double x[N+1];
	NodeType A[N+1];
	for(i=1;i<=N;i++) {cin>>A[i].weight>>A[i].value;A[i].p=A[i].value/A[i].weight;}
	sort(A+1,A+N+1);
	//this is knap function below 
	double weight_left=T;i=1;
	while(A[i].weight<weight_left){
		x[i]=1;weight_left-=A[i].weight;
		value+=A[i].value;i++;
	}
	if(weight_left>0){
		x[i]=weight_left/A[i].weight;
		value+=x[i]*A[i].value;
	}
	printf("%.2lf\n",value);return 0;
}

常见错误:

 修改后的通关代码:

#include<bits/stdc++.h>
using namespace std;
//贪心算法 求解部分可分割背包问题
int N,T;  //N可以表示成背包数量  T可以理解成背包的容量 
double Value;  //用于存储总价值
struct NodeType{
	double w; //物品重量
	double v;//物品价值
	double p; //p=v/w  即单位重量对应的价值
	bool operator<(const NodeType &s) const{
		return p>s.p;  //按照p价值单位比 进行递减排序 
	} 
};
int main(){
	cin>>N>>T;
	NodeType A[N+1];int i; 
	for(i=1;i<=N;i++){
		cin>>A[i].w;cin>>A[i].v;
		A[i].p=A[i].v/A[i].w;
	}
	sort(A+1,A+N+1);//从大到小递减排序
	Value=0.0;
	double weight=T; //用于存储背包能装下的剩余容量
	double x[N+1];  //选择物品与否的装入数组
	memset(x,0,sizeof(x));
	i=1;
	while(A[i].w<weight){
		x[i]=1;
		weight-=A[i].w;
		Value+=A[i].v;
		i++;
	} 
	if(weight>0){  //如果余下重量大于0 说明没有装满
		x[i]=weight/A[i].w;
		Value+=x[i]*A[i].v;
	}
	printf("%.2lf\n",Value);
	return 0;	 
} 

接下来是对这个问题的分析,会给出一些其他变化的算法形式。

贪心法可以用于求解背包问题中的可分割背包问题。

 

 

 

 

 参考代码部分:

//问题表示
int n=5;
double W=100;				//限重
struct NodeType
{  double w;
   double v;
   double p;				//p=v/w
   bool operator<(const NodeType &s) const
   {
	return p>s.p;			//按p递减排序
   }
};
NodeType A[]={{0},{10,20},{20,30},{30,66},{40,40},{50,60}};						//下标0不用
//求解结果表示
double V;				//最大价值
double x[MAXN];
void Knap()			//求解背包问题并返回总价值
{  V=0;				//V初始化为0
   double weight=W;		//背包中能装入的余下重量
   memset(x,0,sizeof(x));	//初始化x向量
   int i=1;
   while (A[i].w<weight)	//物品i能够全部装入时循环
   {  x[i]=1;			//装入物品i
      weight-=A[i].w;		//减少背包中能装入的余下重量
      V+=A[i].v;		//累计总价值
      i++;			//继续循环
   }
   if (weight>0)		//当余下重量大于0
   {  x[i]=weight/A[i].w;	//将物品i的一部分装入
      V+=x[i]*A[i].v;		//累计总价值
   }
}
void main()
{  printf("求解过程\n");
   for (int i=1;i<=n;i++)		//求v/w
     A[i].p=A[i].v/A[i].w;
   printf("(1)排序前\n");dispA();
   sort(A+1,A+n+1);			//A[1..n]排序
   printf("(2)排序后\n"); dispA();
   Knap();
   printf("(3)求解结果\n");		//输出结果
   printf("    x: [");
   for (int j=1;j<=n;j++)
      printf("%g, ",x[j]);
   printf("%g]\n",x[n]);
   printf("    总价值=%g\n",V);
}

针对这道OJ题,对该算法变形后得到的可以通关的算法如下:

 算法分析:这题属于贪心算法中常见的加工生产调度(流水作业调度问题)

可以贪心的思考这个例题最优解的情况。就是让A和B都马不停蹄的进行工作。所以A的选取优先原则是尽可能选择A耗时较少的,让B早点动工。同时也要让B优先加工时间长的,让A少一些等待

参考地址:

https://blog.csdn.net/weixin_42928870/article/details/81701061
https://www.likecs.com/show-460547.html

参考算法1:(时间复杂度会比较高)

#include<bits/stdc++.h>
struct Str { int w;int num;};
bool cmp(Str x, Str y){ return x.w < y.w; }
int main(){
	int n;while(scanf("%d", &n)){
		int a[1010], b[1010];Str s[5000];int u, v;int ans[1010];
		for(int k = 1;k <= n;k ++) scanf("%d", &a[k]); //读入
		for(int k = 1;k <= n;k ++) scanf("%d", &b[k]);
		for(int k = 1;k <= n;k ++) s[k].w = std::min(a[k], b[k]), s[k].num = k;
		std :: sort(s+1, s+n+1, cmp);//结构体存储,s[k].w表示用的时间. s[k].num 表示其序号
		u = 0, v = n+1;
		for(int k = 1;k <= n;k ++)
			if(s[k].w == a[s[k].num]) 
				ans[++ u] = s[k].num;
		    else  ans[-- v] = s[k].num;
		u = 0, v = 0;
		for(int k = 1;k <= n;k ++){
		    u += a[ans[k]];
		    if(v < u)  v = u;
		    v += b[ans[k]];
		}
		printf("%d\n", v);
	}
	return 0;
}

参考算法2:

#include<bits/stdc++.h>
using namespace std;
const int N = 2005;
struct data {
	int id,a,b;
};
inline bool cmp(const data &A, const data &B) {//Jhonson不等式排序 
	return min(A.a, A.b) < min(B.a, B.b);
}
int main() {
	int n;
	while(scanf("%d", &n)){
		data J[N],ans[N];
		for(int i = 1; i <= n; ++i) {
			scanf("%d", &J[i].a);
			J[i].id = i;//原数组下标 
		}
		for(int i = 1; i <= n; ++i) scanf("%d", &J[i].b);
		sort(J + 1, J + 1 + n, cmp);
		for(int i = 1, p = 1, q = n; i <= n; ++i) {//p--队头 q--队尾 
			if(J[i].a <= J[i].b) ans[p++] = J[i];
			else ans[q--] = J[i];
		}
		int time1 = 0, time2 = 0;//time1--A机器上加工用时 time2--B机器上加工用时 
		for(int i = 1; i <= n; ++i) {
			time1 += ans[i].a;//第i件产品在A机器上所用时间 
			time2 = max(time1, time2);//在A机器上加工完才能到B机器 未加工完需要等待 
			time2 += ans[i].b;//第i件产品在B机器上所用时间 
		}
		printf("%d\n", time2);//最后一件在B机器加工完的时刻为结束时刻 
		//for(int i = 1; i <= n; ++i) printf("%d ", ans[i].id);//输出方案 	
	}
	return 0;
}

通关算法:

#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=1010;
struct node//三元组结构
{
    int id;//工作编号
    int ab;//在哪个机器
    int times;//时间
    bool operator < (node tmp)const
    {
        return times<tmp.times;//按时间从小到大排序
    }
};
void johnson(node s[],int n,int a[],int b[],int c[])//Johnson算法 生成三元组表s
{
    for(int i=1;i<=n;i++)
    {
        if(a[i]>b[i])
        s[i].ab=2,s[i].times=b[i];
        else
        s[i].ab=1,s[i].times=a[i];
        s[i].id=i;
    }
    sort(s+1,s+n+1);//按times从下到大排序
    int l=0,r=n+1;
    for(int i=1;i<=n;i++)//生成加工顺序
    {
        if(s[i].ab==1)
        c[++l]=s[i].id;
        if(s[i].ab==2)
        c[--r]=s[i].id;
    }
}
int main()
{
	int n;
	while(cin>>n){
		int a[maxn],b[maxn],c[maxn],t[maxn];
		node s[maxn];
		for(int i=1;i<=n;i++)
	    cin>>a[i];
	    for(int i=1;i<=n;i++)
	    cin>>b[i];
	    johnson(s,n,a,b,c);
	    for(int i=1;i<=n;i++)计算最少时间 
	    t[i]=t[i-1]+a[c[i]];
	    int ans=t[1]+b[c[1]];
	    for(int i=2;i<=n;i++)
	    ans=max(ans,t[i])+b[c[i]];
	    cout<<ans<<endl;//答案	
	}
    return 0;
}

学习地址:

https://www.cnblogs.com/cax1165/p/6070951.html

自行设计的通关算法:

#include<bits/stdc++.h>
using namespace std;
struct A {
	int min;//a,b中较小的那个
	int key;//记录下标
};
inline int cmp(A a,A b){
	return a.min<b.min;
}
int main() {
	int n;
	while(cin>>n){
		int* a = new int[n + 1]();//在A中的加工时间
		int* b = new int[n + 1]();//在B中加工的时间
		int* ta = new int[n + 1]();//在A中加工到第i个物品的总时间
		int* ans = new int[n + 1]();//存放最终加工顺序的下标 
		A* c = new A[n + 1];
		for (int i = 1; i <= n; i++) {
			scanf("%d",&a[i]);
		}
		for(int i=1;i<=n;i++){
			scanf("%d",&b[i]);
			c[i].min=min(a[i],b[i]);
			c[i].key=i;
		}
		sort(c+1,c+n+1,cmp);
		
		int u=1,v=n;//u从头开始,v从末尾开始 
		for(int i=1;i<=n;i++){
			if(c[i].min==a[c[i].key]){//如果小的数是a中的,放前面 
				ans[u]=c[i].key;
				u++;
			}
			else{//如果小的数是b中的,放后面 
				ans[v]=c[i].key;
				v--;
			}
		}
		for(int i=1;i<=n;i++){
			ta[i]=ta[i-1]+a[ans[i]];//计算ta 
		}
	
		int sum=ta[1]+b[ans[1]];
		for(int i=2;i<=n;i++){
			sum=max(ta[i],sum)+b[ans[i]];
		}
		cout<<sum<<endl;
	}
	return 0;
}

 贪心算法之流水作业调度问题

4个作业(编号为14)要在由两台机器M1M2组成的流水线上完成加工。每个作业加工的顺序都是先在M1上加工,然后在M2上加工。M1M2加工作业i所需的时间分别为aibi1≤in)。请给出耗时最少的最优调度方案

编号 

1

2

3

4

M1

5

12

4

8

M2

6

2

14

7

流水作业调度问题要求确定这n个作业的最优加工顺序,使得从第一个作业在机器M1上开始加工,到最后一个作业在机器M2上加工完成所需的时间最少。可以假定任何作业一旦开始加工,就不允许被中断,直到该作业被完成。

[实验提示]

具体做法是:

组号

1

0

1

0

时间time

5

2

4

7

(2)将N1(组号=1, a[i]≤b[i] )的作业按a[i](用时间time存放)递增排序,N2 (组号=0, a[i]>b[i] )的作业按b[i] (用时间time存放)递增排序。数。

编号 

1

2

3

4

M1

5

12

4

8

M2

6

2

14

7

组号

1

0

1

0

时间time

5

2

4

7

编号 

2

3

1

4

M1

12

4

5

8

M2

2

14

6

7

组号

0

1

1

0

时间time

2

4

5

7

(3)按顺序先执行N1的作业(顺序),再执行N2的作业(反序),得到的就是耗时最少的最优调度方案。

编号 

2

3

1

4

M1

12

4

5

8

M2

2

14

6

7

组号

0

1

1

0

时间time

2

4

5

7

编号 

3

1

4

2

M1

4

5

8

12

M2

14

6

7

2

组号

1

1

0

0

时间time

4

5

7

2

最优调度方案:3 1 4 2

    

 [实验步骤]

1求在最优调度下总时间,用f1累计M1上的执行时间(初始时f1=0);f2累计M2上的执行时间(初始时f2=0),最终f2即为最优调度下的消耗总时间。 

    对于最优调度方案best,用i扫描best的元素,f1和f2的计算如下:

       f1=f1+a[best[i]]

       f2=max{f1,f2}+b[best[i]];

2针对问题实例,实录运行时的输入、输出文件;

3将你的程序和截屏的界面存盘备用。

[算法框架]

int solve() //求解流水作业调度问题

{  int i,j,k;

   NodeType c[N];

   for(i=0;i<n;i++) //n个作业中,求出每个作业的最小加工时间 

   {  c[i].no=i;

      c[i].group=(a[i]<=b[i]);

//a[i]<=b[i]对应第1N1,a[i]>b[i]对应第0N2

      c[i].time=a[i]<=b[i]?a[i]:b[i];

//1组存放a[i],0组存放b[i]

   }

   sort(c,c+n); //c元素按time递增排序

j=0; k=n-1;

   for(i=0;i<n;i++) //扫描c所有元素,产生最优调度方案

   {  if(c[i].group==1) //1,time递增排列放在best的前面部分

         best[j++]=c[i].no;

      else //0,time递减排列放到best的后面部分

         best[k--]=c[i].no;

   }

   int f1=0; //累计M1上的执行时间

   int f2=0; //最优调度下的消耗总时间

   for(i=0;i<n;i++)

   {  f1+=a[best[i]];

      f2=max(f2,f1)+b[best[i]];

   }

   return f2;

}

 [算法分析]

算法的主要时间花费在排序上,所以时间复杂度为O(nlog2n)

具体的算法代码实现部分:

#include<bits/stdc++.h>
using namespace std;
struct NodeType{
	int no;bool group;int time;
	bool operator<(const NodeType &s) const{
		return time<s.time;
	}
};
int main(){
	int n;cout<<"please input the number of work:";cin>>n;
	int a[n],b[n];cout<<"please input the time of M1 and M2:";
	for(int i=0;i<n;i++) cin>>a[i]; cout<<"M2:"<<endl;
	for(int i=0;i<n;i++) cin>>b[i];
	int best[n];int j=0,k=n-1;NodeType c[n];
	for(int i=0;i<n;i++){
		c[i].no=i;c[i].group=(a[i]<=b[i]);
		c[i].time=a[i]<=b[i]?a[i]:b[i];
	}
	sort(c,c+n);
	for(int i=0;i<n;i++) if(c[i].group==1) best[j++]=c[i].no; else best[k--]=c[i].no;
	int f1=0,f2=0;
	for(int i=0;i<n;i++){
		f1+=a[best[i]];
		f2=max(f2,f1)+b[best[i]];
	}
	cout<<"total time:"<<f2<<endl;cout<<"plan:";for(int i=0;i<n;i++) cout<<best[i]+1;
	return 0;
} 

 (PS:图中部分字母存在错误 自行修正即可)

 

 

struct NodeType
{  int no;			//作业序号
   bool group;			//1代表第一组N1,0代表第二组N2
   int time;			//a,b的最小时间
   bool operator<(const NodeType &s) const
   {
	return time<s.time;	//用于按time递增排序
   }
};
//问题表示
int n=4;
int a[N]={5,12,4,8};		//对应M1的时间
int b[N]={6,2,14,7};		//对应M2的时间
struct NodeType
{  int no;			//作业序号
   bool group;			//1代表第一组N1,0代表第二组N2
   int time;			//a,b的最小时间
   bool operator<(const NodeType &s) const
   {
     return time<s.time;	//按time递增排序
   }
};
//求解结果表示
int best[N];			//最优调度序列
int solve()		//求解流水作业调度问题
{  int i,j,k;
   NodeType c[N];
   for(i=0;i<n;i++)	//n个作业中,求出每个作业的最小加工时间 
   {  c[i].no=i;
      c[i].group=(a[i]<=b[i]);
			//a[i]<=b[i]对应第1组N1,a[i]>b[i]对应第0组N2
      c[i].time=a[i]<=b[i]?a[i]:b[i];
			//第1组存放a[i],第0组存放b[i]
   }
   sort(c,c+n);	//c元素按time递增排序
 j=0; k=n-1;
   for(i=0;i<n;i++)		//扫描c所有元素,产生最优调度方案
   {  if(c[i].group==1)	//第1组,按time递增排列放在best的前面部分
         best[j++]=c[i].no;
      else			//第0组,按time递减排列放到best的后面部分
         best[k--]=c[i].no;
   }
   int f1=0;			//累计M1上的执行时间
   int f2=0;			//最优调度下的消耗总时间
   for(i=0;i<n;i++)
   {  f1+=a[best[i]];
      f2=max(f2,f1)+b[best[i]];
   }
   return f2;
}
void main()
{  printf("求解结果\n");
   printf("    总时间: %d\n",solve());
   printf("    调度方案: ");
   for(int i=0;i<n;i++)
     printf("%d ",best[i]+1);
   printf("\n");
}

 

 

 

  • 5
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 南京信息工程大学oj系统题库是为了帮助学生提高编程能力、加强算法训练而开设的,题库中包含了各种类型的题目,涵盖了计算机科学与技术、软件工程、网络工程、物联网等专业的知识点。题库中的题目难度有高有低,从初级到高级、从简单到复杂都有涵盖,可以满足不同层次、不同需求的学生。 南京信息工程大学oj系统题库的题目内容丰富多样,可以涉及到各种算法、数据结构、编程语言等方面的知识。学生可以通过解答这些题目,了解和掌握不同算法和数据结构的应用场景,提高编程能力和实践动手能力。 南京信息工程大学oj系统题库的使用非常方便,学生只需登录系统,在题库中选择自己感兴趣或者需要练习的题目,然后根据题目的要求,编写相应的代码进行提交。系统会自动对代码进行评测,给出相应的反馈和评分,帮助学生了解自己的编程能力和解题能力。 同时,南京信息工程大学oj系统题库也可以作为教师授课和学生自学的辅助工具。老师可以根据课程内容,选择合适的题目进行布置作业或者考试,提升学生的学习兴趣和积极性。对于学生自学的话,可以通过解答题库中的题目,巩固和加深对于课程知识的理解和掌握。 总之,南京信息工程大学oj系统题库是一个重要的学习资源,可以帮助学生巩固和提高编程能力,为他们在计算机科学与技术以及相关领域的学习和就业打下坚实的基础。 ### 回答2: 南京信息工程大学oj系统题库是该校为了方便学生进行编程实践和提高编程能力而特别开设的一个在线题库。该题库的目的是帮助学生巩固课堂所学的理论知识,实践编程技巧,并培养学生解决实际问题的能力。 南京信息工程大学oj系统题库中包含了各种难度级别的编程题目,涵盖了计算机科学与技术、通信工程、软件工程等多个专业领域的知识点。学生可以通过选定特定的题目,根据自身编程能力的提升情况逐渐挑战难度更大的题目。 在南京信息工程大学oj系统题库中,学生可以提交自己的代码,系统会自动对代码进行评测并返回结果。这样可以有效地帮助学生查找代码中的错误,并及时进行修改和改进。除此之外,学生还可以查看别人的解题思路和代码实现,借鉴他人的经验,丰富自己的编程思维。 南京信息工程大学oj系统题库还提供了在线编程环境,学生无需安装额外的编译器或者IDE,只需通过浏览器就可以完成编程任务。这样方便学生的学习和实践,并提高了学生在编程中的效率和体验。 总之,南京信息工程大学oj系统题库是一个宝贵的资源,能够提供给学生进行编程实践和提高编程能力的机会。通过挑战不同难度的题目,学生可以不断提升自己的编程水平,更好地适应未来的学习和工作需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Simon_Smith

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值