作业比赛编号 : 1272 - 2022年春季学期《算法分析与设计》练习10

最长递增子序列

题目描述

给出一个序列a1,a2,a3,a4,a5,a6,a7...an,求它的一个子序列(设为s1,s2,...sn),使得这个子序列满足这样的性质:s1<s2<s3<...<sn并且这个子序列的长度最长。输出这个最长子序列的长度,要求时间复杂度为O(n2)。

输入

每组输入包括两行,第一行为序列长度n,第二行为序列。

输出

输出最长递增子序列的长度。

样例输入 Copy

7
1 7 3 5 9 4 8

样例输出 Copy

4

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include<iostream>
#include<algorithm>
using namespace std;
int a[1005];
int dp[1005];
void fun(int n)
{
	for (int i = 0; i < n; i++)
	{
		dp[i] = 1;
	}
	for (int i = 1; i < n; i++)
	{
		int t = 0;
		for (int j = i - 1; j >= 0; j--)
		{
			if (a[j]<a[i] && dp[j] > t)
			{
				t = dp[j];
			}
		}
		dp[i] = t + 1;
	}
}
int main()
{
	int n;
	while (cin >> n)
	{
		for (int i = 0; i < n; i++)
		{
			cin >> a[i];
		}
		fun(n);
		sort(dp, dp + n);
		cout << dp[n - 1] << endl;
		
	}
}


构造最长递增子序列

题目描述

在“最长递增子序列”的基础上对代码进行改进,输出一条最长递增子序列。

输入

每组输入包括两行,第一行为序列长度n,第二行为序列。

输出

输出最长递增子序列中的任意一条即可。

样例输入 Copy

7
1 7 3 4 9 2 3

样例输出 Copy

1 3 4 9

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include<iostream>
#include<algorithm>
using namespace std;
int a[1005];
int dp[1005];
int pre[1005];
int c[1005];
void fun(int n)
{
	for (int i = 0; i < n; i++)
	{
		dp[i] = 1;
	}
	for (int i = 1; i < n; i++)
	{
		int t = 0;
		for (int j = i - 1; j >= 0; j--)
		{
			if (a[j]<a[i] && dp[j] > t)
			{
				t = dp[j];
				pre[i] = j;
			}
		}
		dp[i] = t + 1;
	}
}
int main()
{
	int n;
	int cc = 0;
	int lab = 0;
	int t = 0;
	while (cin >> n)
	{
		for (int i = 0; i < n; i++)
		{
			cin >> a[i];
		}
		fun(n);
		for (int i = 0; i < n; i++)
		{
			if (dp[i] > t)
			{
				t = dp[i];
				lab = i;
			}
		}
		cc = t;
		int j = t;
		int i = lab;
		while (t--)
		{
			c[j - 1] = a[i];
			j--;
			i = pre[i];
		}
	
		for (int i = 0; i < cc; i++)//注意之前我写的i<t,我们这个时候t已经改变了不能i<t了
		{
			cout << c[i] << " ";
		}
		cout << endl;

	}
}


出列人数

有N位同学站在一排,体育老师要请其中的(N-K)位同学出列,将剩下的K位同学从左到右依次编号为1,2,3,…K,他们的身高分别为T1,T2,T3,…TK,要求满足T1<T2<T3<…<TK。已知N位同学的身高,请设计一个算法,计算最少需要几位同学出列可使得剩下的同学满足上述要求。

样例输入 Copy

7
1 7 3 5 9 4 8

样例输出 Copy

3

找出最长递增序列的长度,总长度减去这个就是要出列的人数

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include<iostream>
#include<algorithm>
using namespace std;
int a[1005];
int dp[1005];
void fun(int n)
{
	for (int i = 0; i < n; i++)
	{
		dp[i] = 1;
	}
	for (int i = 1; i < n; i++)
	{
		int t = 0;
		for (int j = i - 1; j >= 0; j--)
		{
			if (a[j]<a[i] && dp[j] > t)
			{
				t = dp[j];
			}
		}
		dp[i] = t + 1;
	}
}
int main()
{
	int n;
	int cc = 0;
	int lab = 0;
	int t = 0;
	while (cin >> n)
	{
		for (int i = 0; i < n; i++)
		{
			cin >> a[i];
		}
		fun(n);
		sort(dp, dp + n);
		cout << n - dp[n - 1] << endl;
	
	}
}


0-1背包问题

题目描述

给定n种物品和一个背包,物品i的重量是Wi,其价值为Vi,背包的容量为C。如何选择装入背包的物品,可以使得装入背包中物品的总价值最大?

输入

每组输入包括三行,
第一行包括物品个数n,以及背包容量C。
第二、三行包括两个一维数组,分别为每一种物品的价值和重量。

输出

输出包括两行,第一行为背包的最大总价值,第二行为所选取的物品。
例如:最大总价值=15,物品选取策略为11001。数据保证答案唯一。

样例输入 Copy

5 10
6 3 5 4 6
2 2 6 5 4

样例输出 Copy

15
11001
#include<iostream>
#include<algorithm>
using namespace std;
int w[1005];
int v[1005];
int dp[1005][1005];
int m[1005];
int fun(int w[], int v[], int n, int c)
{
    int jmax = min(c, w[n - 1] - 1);
    for (int j = 0; j <= jmax; j++)
    {
        dp[n - 1][n] = 0;//填最后一行
    }
    for (int j = jmax + 1; j <= c; j++)
    {
        dp[n - 1][j] = v[n - 1];//填最后一行
    }
    for (int i = n - 2; i >= 0; i--)
    {
        int jmax = min(c, w[i] - 1);
        for (int j = 0; j <= jmax; j++)
        {
            dp[i][j] = dp[i + 1][j];//不放第i个
        }
        for (int j = jmax + 1; j <= c; j++)
        {
            dp[i][j] = max(dp[i + 1][j], dp[i + 1][j - w[i]] + v[i]);//放第i个
        }
    }
    return dp[0][c];
}
void fun2(int w[], int m[], int c, int n)
{
    for (int i = 0; i < n; i++)
    {
        if (dp[i][c] == dp[i + 1][c])
        {
            m[i] = 0;
        }
        else {
            m[i] = 1;
            c = c - w[i];
        }
    }
}
int main()
{
    int n; int c;
    while (cin >> n)
    {
        cin >> c;
        for (int i = 0; i < n; i++)
        {
            cin >> v[i];
        }
        for (int i = 0; i < n; i++)
        {
            cin >> w[i];
        }
        cout << fun(w, v, n, c) << endl;
        fun2(w, m, c, n);
        for (int i = 0; i < n; i++)
        {
            cout << m[i];
        }
        cout << "\n";

    }


}

 XP的午餐

题目描述

XP每天都会思考一个问题,今天午餐去哪里吃?这是一个很重要的问题,这会影响到他下午的体力值。他的午餐预算是M元,现在有N种菜品,每一种菜品的价格和能够提供的体力值已知(每种菜品只能选择一次),请问如何选择菜品能够让XP下午的体力值最大呢?

输入

多组输入
第一行:M元和菜品数量N。
接下来N行,每一行两个整数,分别表示每一种菜品的价格(vi)和能够获得的体力值(wi)。
(0<N<=20,0<=M<=1000)(0<=vi<=50,0<=wi<=100)

输出

最大体力值。

样例输入 Copy

10 5
1 5
2 4
3 3
4 2
5 1

样例输出 Copy

14
#include<iostream>
#include<algorithm>
using namespace std;
int dp[2000][2000];
int v[2000];
int w[2000];
 
 
int fun(int v[], int w[], int m, int n) {
 
    int jmax = min(m, v[n - 1] - 1);
 
    for (int j = 0; j <= jmax; j++)
 
        dp[n - 1][j] = 0;
 
    for (int j = jmax + 1; j <= m; j++)
        dp[n - 1][j] = w[n - 1];
    for (int i = n - 2; i >= 0; i--)
 
    {
 
        int jmax = min(m, v[i] - 1);
 
        for (int j = 0; j <= jmax; j++)
 
            dp[i][j] = dp[i + 1][j];
 
        for (int j = jmax + 1; j <= m; j++)
 
            dp[i][j] = max(dp[i + 1][j], dp[i + 1][j - v[i]] + w[i]);
    }
    return dp[0][m];
 
}
 
int main() {
    int m;
    int n;
    while (~scanf("%d %d", &m, &n)) {
 
        for (int i = 0; i < n; i++)
        {
            scanf("%d %d", &v[i], &w[i]);
        }
        int z = fun(v, w, m, n);
        printf("%d\n", z);
 
    }
    return 0;
}
 

 补充能量

#include<iostream>
#include<algorithm>
using namespace std;
int w[1005];
int v[1005];
int dp[1005][1005];
int m[1005];
int fun(int w[], int v[], int n, int c)
{
    int jmax = min(c, w[n - 1] - 1);
    for (int j = 0; j <= jmax; j++)
    {
        dp[n - 1][n] = 0;//填最后一行
    }
    for (int j = jmax + 1; j <= c; j++)
    {
        dp[n - 1][j] = v[n - 1];//填最后一行
    }
    for (int i = n - 2; i >= 0; i--)
    {
        int jmax = min(c, w[i] - 1);
        for (int j = 0; j <= jmax; j++)
        {
            dp[i][j] = dp[i + 1][j];//不放第i个
        }
        for (int j = jmax + 1; j <= c; j++)
        {
            dp[i][j] = max(dp[i + 1][j], dp[i + 1][j - w[i]] + v[i]);//放第i个
        }
    }
    return dp[0][c];
}
//void fun2(int w[], int m[], int c, int n)
//{
//    for (int i = 0; i < n; i++)
//    {
//        if (dp[i][c] == dp[i + 1][c])
//        {
//            m[i] = 0;
//        }
//        else {
//            m[i] = 1;
//            c = c - w[i];
//        }
//    }
//}
int main()
{
    int n; int c;
    while (cin >> n)
    {
        cin >> c;
        for (int i = 0; i < n; i++)
        {
            cin >> w[i];
        }
        for (int i = 0; i < n; i++)
        {
            cin >> v[i];
        }
         
        cout << fun(w, v, n, c) << endl;
      
 
    }
 
 
}

最少硬币 

题目描述

假设有4种硬币,它们的面值分别为1分、5分、10分和25分。
现在要找给顾客n分钱。
请问怎样找零钱才能使给顾客的硬币个数最少?
输出所需最少硬币的枚数。

输入

输入需要找给顾客的零钱n(单位:分)。

输出

输出所需最少硬币的枚数。

样例输入 Copy

8
10
63

样例输出 Copy

4
1
6
#include <stdio.h>
#include <stdlib.h>
 
int main()
{
    int n;
    int a[] = { 25,10,5,1 };
    int sum = 0;
    while (~scanf("%d", &n)) {
         sum = 0;
        while (n) {
            if (n >= a[0]) { n -= a[0]; sum++; }
            else if (n >= a[1]) { n -= a[1]; sum++; }
            else if (n >= a[2]) { n -= a[2]; sum++; }
            else if (n >= a[3]) { n -= a[3]; sum++; }
        }
        printf("%d\n", sum);
    }
    return 0;
}
 

 

题目描述

某图书销售管理系统需要对图书(Book)进行排序,每一本图书包含书名(bookName)、销量(bookSales)、价格(bookPrice)等属性,要求先按照销量由大到小排序,对于销量相同的图书再按照价格由小到大排序。

输入

每组输入包括两个部分,第一部分为书的数量n,
接下来n行则为n本书的信息。 按顺序输入书名(不超过20个字)、销量、价格。

输出

输出排序后的信息,每个属性用空格隔开

样例输入 Copy

7
C++程序设计 120 25.00
软件工程 96 48.00
高等数学 80 32.50
算法分析与设计 96 54.00
离散数学 96 28.00
计算机网络 96 36.00
操作系统 115 45.00

样例输出 Copy

C++程序设计 120 25.00
操作系统 115 45.00
离散数学 96 28.00
计算机网络 96 36.00
软件工程 96 48.00
算法分析与设计 96 54.00
高等数学 80 32.50
#include <iostream>
#include <iomanip>
#include <algorithm>
using namespace std;
struct book {
    //利用结构体对其排序
    string name;
    int num;
  double price;
};
int cmp1(const book& a, const book& b) {
    if (a.num != b.num)
        return a.num > b.num;
    else
        return a.price < b.price;
}
 
int main()
{
    int n;
    book b[1005];
    while (cin >> n) {
        for (int i = 0; i < n; i++) {
            cin >> b[i].name;
            cin >> b[i].num;
            cin >> b[i].price;
 
        }
        sort(b, b + n, cmp1);
 
        for (int i = 0; i < n; i++) {
            cout << b[i].name << ' ' << b[i].num << ' ';
            printf("%.2f\n", b[i].price);
         
           
        }
    }
    return 0;
}

道具的魅力值 

题目描述

在某网络游戏中提供了一个道具库,在道具库中每种道具均有若干件(数量已知),游戏玩家购买一件道具将获得一定的魅力值。
已知每种道具的价格和魅力值,请编写一个程序,在总价格不超过某个上限的情况下使得所购道具的魅力值之和达到最大。

输入

每组测试数据的输入有n+1行,n表示道具的种类。(n<=100,p<=10000)
第1行包含两个正整数,分别表示道具种类数n和总价值的上限p,两个数字之间用空格隔开。
第2行到第n+1行分别对应于第1种道具到第n种道具的信息,每1行包含三个正整数,两个数字之间用空格隔开,三个正整数分别表示某一种道具的数量、单个道具的价格和魅力值。

输出

每组测试数据的输出只有一行,即道具魅力值的最大和。

样例输入 Copy

3 10
2 2 3
1 5 10
2 4 12

样例输出 Copy

27

 

#include <iostream>
#include<string.h>
using namespace std;
int dp[10005], n, t, v, w, s;
int main()
{
 
    while (cin >> n >> t)
    {
        memset(dp, 0, sizeof(dp));
        while (n--)
        {
            cin >> s >> w >> v;
            for (int i = 1; i <= s; i++)
                for (int j = t; j >= w; j--)
                    dp[j] = max(dp[j], dp[j - w] + v);
        }
        cout << dp[t];
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值