2973. 卡片游戏

Kuroko

才看到N <= 100,直接暴力就好了……为什么要写算法呢……为什么呢……

10175101214

题目有bug,应该是1<=m<=300000,不是30000吧!否则一直Runtime Error啊!

Li Dao

一种做法

include

using namespace std;
int T,n,m;
vector V;
int find(int aa,int bb)
{
int val=m-V[aa]-V[bb];
int left=0,right=V.size()-1,ans=-1;
while(left<=right)
{
int mid=(left+right)/2;
if(V[mid]<=val)
{
if(mid!=aa && mid!=bb) ans=max(ans,V[mid]+V[aa]+V[bb]);
left=mid+1;
}
else right=mid-1;
}
return ans;
}
int main()
{
cin>>T;
for(int step=0;step>n>>m;
V.clear();
for(int i=1;i<=n;i++)
{
int xx;
cin>>xx;
V.push_back(xx);
}
sort(V.begin(),V.end());
int ans=-1;
for(int i=0;i<V.size();i++)
for(int j=i+1;j<V.size();j++)
if(V[i]+V[j]<m) ans=max(ans,find(i,j));
printf(“case #%d:\n%d\n”,step,ans);
}
return 0;
}

一个数组上选择三个不同位置的数,使得三个数的和在不超过M的前提下最大,求最大值

明摆着,出题人是想要我们枚举两个数,二分查找第三个数
而二分查找的前提是排序完成。
复杂度为nnlog(n)

当然,还有一种做法,当做背包问题来做,不过一般的背包问题,只能决定有几个物体供选择,而不能决定实际上选择了几个
背包写的有点想吐了。以后有心情再来写。

SmallY
#include <bits/stdc++.h>

using namespace std;


int main()
{
    int T;
    scanf("%d", &T);
    for(int i = 0; i < T; ++i){
        int N, M;
        scanf("%d%d", &N, &M);
        int bag[M+1];
        memset(bag, 0, sizeof(bag));
        bag[0] = 1;
        int item[N];
        for(int j = 0; j < N; ++j){
            scanf("%d", item+j);
        }
        for(int n = 0; n < N; ++n){
            for(int m = M; m >= item[n]; --m){
                if(bag[m-item[n]]){
                    if(!bag[m] && m == item[n])  //初始化
                        bag[m] = 1;
                    else if(!bag[m] || bag[m] > bag[m-item[n]]+1)  //用尽可能少的牌得到更多的分数
                        bag[m] = bag[m-item[n]]+1;
                }
            }
        }
        int m = M;
        while(m > 0){
            if(bag[m] == 3)  //找到用3张牌可以得到的最大分数
                break;
            m--;
        }
        printf("case #%d:\n%d\n", i, m);
    }
    return 0;
}
10175102262 LarsPendragon

二分查找?需要二分查找吗……感觉完全不用,附C代码:

#include <stdio.h>
#include <stdlib.h>
int cmp(const void *a, const void *b)
{
    int *p1=(int*)a, *p2=(int*)b;
    return *p2-*p1;
}
int main()
{
    int T, I;
    scanf("%d",&T);
    for(I=0; I<T; I++)
    {
        int n, m, i, j, k, num[100], x, max=0;
        scanf("%d %d",&n,&m);
        for(i=0; i<n; i++) 
        {
            scanf("%d",&num[i]);
            if(num[i]>=m-1) {i--; n--;}
        }
        qsort(num, n, sizeof(int), cmp);//从大到小排序
        for(i=0; i<n-2; i++)
            for(j=i+1; j<n-1; j++)//遍历前两个数
            {
                x=num[i]+num[j];
                if(x>=m) continue;
                else
                {
                    for(k=j+1; k<n; k++)//判断第三个数
                        if(num[k]<=m-x)
                        {
                            if(max<x+num[k]) max=x+num[k];
                            break;
                        }
                }
            }
        printf("case #%d:\n%d\n",I,max);
    }
    return 0;
}
FisherKK

不会吧不会吧,这道naive还有人写了很久吗,太简单了吧!

#include <iostream>
#include <bits/stdc++.h>
#include <cctype>
#include <cmath>
#include <algorithm>
using namespace std;
typedef long long LL;
#define Check(a, b) (a >= 0 && a < h && b >= 0 && b < w) 
int T, N, M, sum = 0;
int Arr[100];
void solve();
int main() {
    #ifndef ONLINE_JUDGE
    freopen("a.txt", "r", stdin);
    #endif
    cin >> T;
    for (int i = 0; i < T; i++) {
        cout << "case #" << i << ":\n";
        solve();
    }

}
void solve() {
    cin >> N >> M;
    sum = 0;
    int maxn = 0;

    for (int i = 0; i < N; i++) cin >> Arr[i];
    for (int i = 0; i < N; i++) {
        for (int j = i + 1; j < N; j++) {
            for (int k = j + 1; k < N; k++) {
                sum = Arr[i] + Arr[j] + Arr[k];
                if (sum > maxn && sum <= M) maxn = sum;
            }
        }
    }
    cout << maxn << endl;

}
Master X

想到一个笑话……
既然有库函数,还自己写排序干嘛
同理?
既然不会超时,还花时间写背包,排序,贪心干嘛……
mmp

你当前正在回复 博客/题目
存在问题!