题目描述
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
听说这题可以贪心?
……
不会贪心,一时想不到。
算了一下大暴搜是
…
=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
****************************************************************/