Team Match

博客围绕编程竞赛组队问题展开,教练Mr Z带n名选手参赛,每队3人,团队能力按特定公式计算,不低于金牌水平m可获金牌。题目给出输入输出要求及样例,作者因想不到贪心算法,采用大暴搜加剪枝的方法解决,复杂度约1e7。

题目描述

The programming competition not only depends on the programmers, but also directed by the coaches. Mr Z is a coach who direct n players to take part in the Guangxi Province Collegiate Programming Contest. We assume that a team is consisted of 3 players whose ability is x, y, z respectively and x >= y >= z. Then the team’s total ability is 3 * x + 2 * y + 1 * z; And for a team, if its ability is not lower than the gold medal level m, the team will certainly win the gold medal. Mr Z would like to match teams to gain as many gold medals as possible, could you tell him how many gold medals it is?

输入

The first line is an integer T which indicates the case number.
And as for each case, there will be 2 lines.
In the first line, there are 2 integers n m, which indicate the number of players, the gold medal level respectively. Please remember n is always the multiple of 3.
In the second line, there are n integers which represents everyone’s ability.
It is guaranteed that——
T is about 100.
for 100% cases, 1 <= n <= 15, 1 <= m <= 30, 1 <= a[i] <= 20.

输出

As for each case, you need to output a single line.
There should be an integer in the line which means the gold medal teams Mr Z could match.

样例输入

2
6 18
3 3 3 4 2 2
6 7
1 1 1 1 1 1

样例输出

2
0

Solution

听说这题可以贪心?
……
不会贪心,一时想不到。
算了一下大暴搜是C215C152C213C132C23C32=15*7*6*11*9*4*3*5*3≈1e7的复杂度,再加剪枝也就过了
这次复杂度算对了……

#include <bits/stdc++.h>
using namespace std;
const int MX=20;
int n,m,a[MX],x,ans;
int l,r,p;
bool vis[MX],Lin[MX][MX][MX];
bool cmp(int A,int B) {
    return A>B;
}
void dfs(int sum) {
    ans=max(ans,sum);
    if(ans==n/3) return;
    int cnt=0,ii=0,res=0;
    while (cnt<3) {
        while (vis[ii]) ii++;
        res+=a[ii]*(3-cnt);
        cnt++;
        ii++;
    }
    if (res<m) return;
    int i,j,k,x;
    for (i=0;i<n-2;++i)
        if (!vis[i]) {
            vis[i]=true;
            for (j=i+1;j<n-1;++j)
                if (!vis[j]) {
                    vis[j]=true;
                    k=n-1;
                    x=m-a[i]*3-a[j]*2;
                    while ((vis[k]||a[k]<x)&&k>j) k--;
                    if (k>j) {
                        vis[k]=true;
                        //printf("(%d,%d,%d) ",i,j,k);
                        dfs(sum+1);
                        vis[k]=false;
                    }
                    vis[j]=false;
                }
            vis[i]=false;
        }
}
int main() {
    int T,i,j,k;
    scanf("%d",&T);
    while (T--) {
        scanf("%d%d",&n,&m);
        ans=0;
        for (int i=0; i<n; ++i) scanf("%d",&a[i]);
        sort(a,a+n,cmp);
        for (i=0; i<n-2; ++i)
            for (j=i+1; j<n-1; ++j) {
                x=m-3*a[i]-2*a[j];
                for (k=n-1; k>j; --k) if (a[k]>=x) break;
                if (a[k]>=x&&k>j) {
                    vis[i]=vis[j]=vis[k]=true;
                    //printf("(%d,%d,%d) ",i,j,k);
                    dfs(1);
                    //printf("\n");
                    vis[i]=vis[j]=vis[k]=false;
                }
            }
        printf("%d\n",ans);
    }
    return 0;
}

/**************************************************************
    Problem: 7136
    User: St085
    Language: C++
    Result: 正确
    Time:8 ms
    Memory:1708 kb
****************************************************************/
### nGQL 中 MATCH 语法的用法 nGQL 是 Nebula Graph 的查询语言,其 `MATCH` 语法用于在图数据库中查找节点和边。以下是对 `MATCH` 语法的详细说明以及示例[^1]。 #### 基本语法 `MATCH` 语句的基本结构如下: ```ngql MATCH pattern [WHERE condition] [RETURN expressions] ``` - **pattern**: 表示要匹配的图模式,包括节点和边。 - **condition**: 可选的过滤条件,用于限制匹配结果。 - **expressions**: 指定返回的结果字段。 #### 示例:基本查询 假设有一个图数据库包含两个标签 `player` 和 `team`,以及一个边类型 `serve`,表示球员为某支球队效力的关系。以下是一个简单的 `MATCH` 查询示例: ```ngql MATCH (p:player)-[s:serve]->(t:team) RETURN p.name, t.name, s.start_year ``` 此查询会返回所有球员的名字、他们所效力的球队名字以及开始效力的年份[^2]。 #### 示例:带条件过滤 如果需要进一步筛选数据,可以在 `WHERE` 子句中添加条件。例如,查询从 2010 年之后开始效力的球员: ```ngql MATCH (p:player)-[s:serve]->(t:team) WHERE s.start_year > 2010 RETURN p.name, t.name, s.start_year ``` #### 示例:聚合操作 `MATCH` 语句可以结合聚合函数使用。例如,统计每个球队的球员数量: ```ngql MATCH (p:player)-[:serve]->(t:team) RETURN t.name AS TeamName, COUNT(p) AS PlayerCount ``` #### 示例:多层关系查询 `MATCH` 支持复杂的多层关系查询。例如,查询某个球员的所有队友(即与该球员在同一支球队效力的其他球员): ```ngql MATCH (p1:player)-[:serve]->(t:team)<-[:serve]-(p2:player) WHERE p1 <> p2 AND p1.name = "PlayerA" RETURN p2.name ``` #### 注意事项 - 在 `MATCH` 语句中,节点和边的标签是可选的,但如果指定标签,可以提高查询性能。 - 条件过滤(`WHERE`)可以帮助缩小查询范围,减少不必要的计算。 - 返回的结果可以通过 `AS` 关键字进行重命名,以便于阅读和后续处理。 ```ngql MATCH (p:player)-[s:serve]->(t:team) RETURN p.name AS PlayerName, t.name AS TeamName, s.start_year AS StartYear ``` ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值