アルゴリズムの質問 - C++/Python (6)

強くなったけど、まだまだ足りない…

筆記試験の問題が弱くなったせいかもしれません。

  1. 奨学金AC

不合格科目がある場合、つまりスコアが 60 点未満の場合は、奨学金を受け取ることができず、「いいえ」と出力されます。

異常がない場合は全得点の平均を計算し基準と比較し、基準以上であれば「はい」、そうでない場合は「いいえ」を出力します。

平均スコアを計算します: (合計 (単一科目のスコア * 単位)) / (単位の合計)

入力: データセットの数、データセット内の被験者の総数 + 標準スコア、各科目の単位、各科目のスコア

出力: 「はい」/「いいえ」

#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. Xiaomei は暴力を使わずにサイコロを投げます 0.27
    時間制限: 1000MS
    メモリ制限: 65536KB
    タイトルの説明:
    Xiaomei はサイコロを振る必要があります。一般的な6面サイコロとは異なり、Xiaomeiでは合計n面のサイコロが必要で、各面の数字も一般的なものとは異なり、n面の数字はa1、a2、...となる必要があります。それぞれ。もちろん、サイコロは正の n 面体であり、唯一の法的要件は、数字 1、2、3、4、2、3 の 6 面サイコロなど、すべての反対側の合計が等しい必要があることです。 , そうすると、上記の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
    タイトル説明:
    Xiaomei が長さ n の 01 文字列 (文字 0 と 1 だけを含む文字列) を渡しますこの文字列の接頭辞と接尾辞を削除できます (空にすることもできます)。つまり、元の文字列の連続した部分文字列を保持します。操作後の文字列全体のコストは、次の 2 つの部分の合計になります。

    (1) 削除された文字数 1;
    (2) 残りの部分文字列の文字数 0
    操作のコストを最小限に抑えて出力する必要があります。
    入力説明:
    長さ n の 01 の文字列を 1 行だけ入力します。
    すべてのデータについて、1≤n≤105
    出力の説明:
    最小操作コストを表す整数を 1 行のみ出力します。

    このアイデアは、ターゲット文字列をプレフィックス、中間文字列、サフィックスの 3 つの部分に分割することです。

    プレフィックスは 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. Xiaomei プレイングコンテスト 0.18
    制限時間: 1000MS
    メモリ制限: 65536KB
    タイトル説明:
    Xiaomei はコンテストに参加しています。

    このコンテストには合計 2^k 人の個人 (シャオメイを含む) が参加しており、番号は 1、2、...、2^k であり、最初は全員が同じグループに属します。競争の手順は次のとおりです。現在のグループに n 人(n は偶数)いるとすると、最初の n/2 人が新しいグループに分けられ、最後の n/2 人が新しいグループに分けられます。新しいグループに分割され、その後、2 つのグループが 2 つのグループに分割されます。競争して、それぞれの勝者を決定し、その後、2 つのグループの勝者が競争し、元のグループの勝者が決まるまで、勝者が現在のグループの勝者となります。グループが決まります。もちろん、その人のグループの勝者はその人自身でなければなりません。

    たとえば、現在のグループに 4 人がいて、1、2、3、4 の番号が付けられている場合、1、2 人はグループに分けられ、3、4 人はグループに分かれて別々に競争され、勝者が決定されます。 1、2、3 の勝者が再度競い合い、グループ全体の勝者を決定します。

    人それぞれ能力が異なるため、シャオメイは全員の 2 対 2 競争の勝者を予測しました。そして今度は、シャオメイは最終的な勝者が誰であるかを知りたいと考えています。

    入力の説明
    最初の行は正の整数 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 つの点で十分です。

    テストデータ:

    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;
    }
    

おすすめ

転載: blog.csdn.net/daxuanzi515/article/details/130319412