算法题-C++/python(6)

我变强了,但是仍然不够…

也许是笔试题变弱了也说不定

  1. 奖学金 AC

有挂科的某一门,即分数小于60,就不能获得奖学金,输出“No”

没有挂科,计算所有分数的均值与标准比较,大于等于标准分数,输出“Yes”,反之输出"No"

计算均值分:(sum(单科成绩*学分))/(学分总和)

输入:数据组数、一组数据里学科总数+标准分数、每个学科的学分、每个学科的分数

输出:“Yes”/“No”

#include<bits/stdc++.h>
using namespace std;
int t;
const int N = 1005;
int n,avg;
int s[N];
int f[N];
int main()
{
	cin>>t;
	while(t--)
	{
		scanf("%d%d",&n,&avg);
		int target = 0,SUM = 0;
		bool flag = false;
		for(int i=0;i<n;i++)
		{
			scanf("%d",&s[i]);
			SUM+=s[i];
		}
		for(int i=0;i<n;i++)
		{
			scanf("%d",&f[i]);
			if(f[i]>=60)
				target+=f[i]*s[i];
			else{
				flag = true;
			}
		}
		if(flag == false)
		{
			if(target/SUM >= avg)
				cout<<"Yes"<<endl;
			else
				cout<<"No"<<endl;
		}
		else
		{
			cout<<"No"<<endl;
		}
	}
	return 0;
 } 

  1. 小美投骰子 没暴力出来 0.27
    时间限制: 1000MS
    内存限制: 65536KB
    题目描述:
    小美需要制作一个骰子。与一般的六面骰子不同,小美需要的骰子总共有 n 面,而且每一面的数字也不同于一般的,这n面的数字需要分别是a1,a2,…an 。当然,骰子是一个正n面体,而且唯一合法的要求是所有相对的两面之和都需要相等,比如一个数字分别为 1,2,3,4,2,3 的六面骰子,那么上面1,下面4,前面2,后面3,左边2,右边3就是合法的方案。
    因为方案可以很多,所以小美并不在乎究竟是怎么做出这样一个骰子,小美只想知道是否能做出一个合法的骰子。当然,保证n为偶数。
    输入描述:
    第一行一个整数T,表示询问数据组数。
    对于每组询问:
    第一行一个正整数n,表示骰子的面数。
    接下来一行每行n个整数,分别为 a1,a2,…,an。
    设N=所有询问数据的n之和。
    对于所有的数据, 1≤T≤100, 1≤N≤105,1≤ai≤105,n为偶数。
    输出描述:
    对于每组询问,输出"YES"或者"NO"(不包含引号)表示能否拼成骰子。

    C++的垃圾暴力,直接用特殊条件判断

#include<bits/stdc++.h>
using namespace std;
int t;
int n;
const int N=105;
int a[N];
long long SUM;
int main()
{
	cin>>t;
	while(t--)
	{
		cin>>n;
		if(n%2==1)
		{
			cout<<"NO"<<endl;
			continue;
		} 
		else if(n==2)
		{
			cout<<"YES"<<endl;
			continue;
		}
		for(int i=0;i<n;i++)
		{
			scanf("%d",&a[i]);
			SUM+=a[i];
		}
		long long c = n/2;
		if(SUM % c==0) cout<<"YES"<<endl;
		else cout<<"NO"<<endl;
		// 任选两个数 和为固定值... 
	}
	return 0;
}

写不出来直接用python莽一个

# 排序 加和==n+1
def solve(n, a):
    # 将数字按照从小到大的顺序排列
    a.sort()
    # 判断每组相对的数字之和是否相等
    for i in range(n//2):
        if a[i]+a[n-1-i] != a[0]+a[n-1]:
            return "NO"
    # 判断每个数字的相对数字是否符合要求
    cnt = [0] * (n+1)
    for i in range(n):
        j = n-1-i
        cnt[a[i]] += 1
        cnt[a[j]] += 1
        if cnt[a[i]] != cnt[a[j]]:
            return "NO"
    return "YES"

n = int(input())
a = list(map(int, input().split()))
print(solve(n, a))
  1. 种田 AC

    有N种作物,它们的购入价值是ai,卖出价值是bi,成熟消耗天数是ti。

    有一块地,可以种M天,问过M天之后,能够获得的最大价值是多少?

    嗯,完全背包板子题,直接写就行了,不分析了。

#include<bits/stdc++.h>
using namespace std;
int n,m;
const int N = 1e6;
int a[N],b[N],t[N],c[N]; 
int f[N];
int main()
{
	cin>>n>>m;
	for(int i=0;i<n;i++)
		scanf("%d",&t[i]);
	for(int i=0;i<n;i++)
		scanf("%d",&a[i]);
	for(int i=0;i<n;i++)
	{
		scanf("%d",&b[i]);	
		c[i] = b[i]-a[i];
	}
	// 完全背包? 
	for(int i=0;i<n;i++)
	{
		for(int j=t[i];j<=m;j++)
			f[j] = max(f[j],f[j-t[i]]+c[i]);
	}
	cout<<f[m]<<endl;
	return 0;
}
  1. 删除01串 0.27 刚刚开始做就觉得阴间 又是一题讨巧的
    时间限制: 1000MS
    内存限制: 65536KB
    题目描述:
    小美给你一个长度为 n 的01串(仅包含字符0和1的串),你可以删除这个串的一个前缀和一个后缀(可以为空),即保留一个原串的连续子串,操作之后整个串的代价为下面两部分之和:

    (1)被删除的字符1的个数;
    (2) 剩下的子串的字符0的个数
    你需要最小化操作的代价,并将其输出。
    输入描述:
    输入仅一行,一个长度为 n 的01字符串。
    对于所有数据,1≤n≤105
    输出描述:
    输出仅一行,一个整数,表示最小的操作代价。

    思路是把目标字符串拆分成三个部分:前缀、中间字串、后缀

    前缀统计1的个数,后缀统计1的个数 ->删除1有花费

    中间子串统计0的个数 ->保留0的花费

    s = input()
    def min_cost(s):
        n = len(s)
        ans = float('inf')
        zeros = s.count('0')
        ones = s.count('1')
        if zeros == 0 or ones == 0 or zeros == n:
            return 0
        # 只删除前缀或后缀的情况
        ans = min(ans, s.count('0'))# cost = 子串里有0个数
        for i in range(n):
            for j in range(n-1, i,-1):
                cost = s[:i].count('1') + s[j:n-1].count('1')
                if i < j:
                    cost += s[i:j].count('0')
                ans = min(ans, cost)
        return ans
    
    print(min_cost(s))
    
    // 用python写出来了 这里可以用c++改装一下
    #include<bits/stdc++.h>
    using namespace std;
    // algorithm里面有count函数 可以统计string里的字符个数 
    int min_cost(string s) {
        int n = s.size();
        int ans = INT_MAX;
        int c0 = 0;
        for (char c : s) {
        	if(c=='0') c0+=1;
        }
        if (c0 == 0 || c0 == n) {
            return 0;
        }
        ans = min(ans, c0); // 只删除前缀或后缀的情况
        for (int i = 0; i < n; i++) {
            for (int j = n-1; j >=0; j--) {
                int cost = count(s.begin(), s.begin()+i, '1') // 前缀的1个数 
                         + count(s.begin()+j, s.end(), '1'); // 后缀的1个数 
                if (i < j) {
                    cost += count(s.begin()+i, s.begin()+j, '0');// 中间串的0个数 
                }
                ans = min(ans, cost);
            }
        }
        return ans;
    }
    
    int main() {
        string s;
        cin >> s;
        cout << min_cost(s) << endl;
        return 0;
    }
    
  2. 小美打比赛 0.18
    时间限制: 1000MS
    内存限制: 65536KB
    题目描述:
    小美正在参加一个比赛。

    这个比赛总共有 2^k 个人参加(包括小美),编号为1,2,…,2^k,开始的时候所有人都在同一个小组。比试的规程如下:假设当前小组有 n 个人(n 为偶数),那么编号大小前 n/2 人分为一个新的小组,后 n/2 人分为一个新的小组,然后两个小组内部分别比试,决出各自的胜者,然后两个小组的胜者进行比试,胜者作为当前小组的优胜者,直到决出最初的小组的优胜者。当然一个人的小组优胜者肯定是他自己。

    例如如果当前小组有 4 个人,编号为1,2,3,4,那么就会将 1,2 分为一组,3,4分为一组分别比试,然后 1,2 中的胜者和 3,4 中的胜者再进行比试,决出整个小组的胜者。

    由于每个人的能力各不相同,小美预测了所有人两两比试时的胜者,现在小美想知道预测最终的胜者是谁。

    输入描述
    第一行一个正整数k ,表示总人数为2^k 。

    接下来2^k行,第 i 行2^k个整数 。

    其中v[i,j]=i 或 j 表示 i , j 进行比试的胜者。

    对于所有的数据,1≤k≤8, 1≤v[i,j]≤2^k

    输出描述
    输出一个整数表示最后的胜者的编号。

    思路没有,就是菜。

    后面问chatgpt写的,不过也是我自己改好的,它自己写的会出错。

    一个简单递归加二分就可以了。

    测试数据:

    2
    1 2 3 1
    2 2 3 2
    3 3 3 3
    1 2 3 4

    输出:3

    #include<bits/stdc++.h>
    using namespace std;
    const int MAXN = 1 << 8;
    int k;
    int v[MAXN + 5][MAXN + 5];
    int c;
    // 比赛函数
    int compete(int l, int r) {
        if (l == r) return l;
        int m = (l + r) / 2;
        int w1 = compete(l, m);
        int w2 = compete(m + 1, r);
    //    cout<<"w1:"<<w1<<" w2:"<<w2<<" v[w1][w2]:"<<v[w1][w2]<<endl; 
    //    cout<<c++<<endl; 
        if(v[w1][w2]==w2) 
        {
        	return w2;
    	}
    	else
    	{
    		return w1;
    	}
    }
    
    int main() {
        cin >> k;
    //    cout<<(1<<k)<<endl;  // 注意左移1位的话 ->*2 
        for (int i = 1; i <= 1<<k; i++) {
            for (int j = 1; j <= 1<<k; j++) {
                cin >> v[i][j];
            }
        }
        cout << compete(1, 1<<k) << endl;
        return 0;
    }
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值