[dp]1396:Select Team

来源:互联网 发布:java poi api下载 编辑:程序博客网 时间:2024/05/22 14:25

Description

As we know, ACM competition is not only based on personal talents, but also team works. A team can be outstanding once it combines these two factors.
A school has N ACM contest candidates. The coach wants to select K candidates from N candidates and sends them to Xiangtan Invitational Programming Contest. We suppose every team has 3 members and every member has a value A that represents the personal skills. Every pair of members has a value W that shows the teamwork skills for that pair. There are 3 members a, b, c in a team then the integral skills of this team represents as following formula:
A[a]+A[b]+A[c]+W[a][b]+W[a][c]+W[b][c];
In the rules of the contest, team score is very important. A coach hope to set K teams up and the total team score is maximum.
Can you figure out what the maximum score of K teams if reasonably choosing team members from contest candidates?
Input

The first line has a integer T (T <=10) represents the number of cases. For each test cases, the first line has two numbers K, N (1 <= K <= 6, 3*K<=N<=18) which show the number of teams and the number of candidates. The second line has N integers A1.. An ,(0<=Ai<=100000) which represents the personal talent or personal skills for each candidates. The following N lines, every line has N integers which is a matrix Wnn. Wij describe the teamwork skill between team member i and j, 0<=Wij<=100000,and Wij=Wji.

Output

 For every case, output a integer which is maximum score for K teams.


Sample Input

11 410 10 10 110 15 5 015 0 15 155 15 0 50 15 5 0
Sample Output

66



题目大意:

有n个ACM竞赛队员,从中选出k个队参加比赛,每个队员有自身的能力值A,每两个队员之间有配合值W。

   A[a]+A[b]+A[c]+W[a][b]+W[a][c]+W[b][c] 为a,b,c三人组成队伍的实力。

 按照最佳策略组队,求这k个队伍的最大实力总和

n比较小,使用位压缩的动态规划来做

整数s第i位为0表示第i个人还未被选入这k个人的队伍中,1表示第i个人已经被选。

F[s]表示s所对应的状态能选出的队伍最大实力值总和

因为永远是3个人一队,状态s已经能确定队伍数量,不需额外记录队伍数量

转移:每次转移选出一整只队伍

枚举s中第一个人是与哪两个人组队的即可,转移复杂度n^2




#include<iostream>#include<cstring>#include <bitset>#include<cstdio>using namespace std;const int MAXN = (1 << 18);int w[MAXN], f[MAXN], bcnt[MAXN], g_k, g_n;void reader(){      int i, j, t, a[20];      scanf("%d%d", &g_k, &g_n);      for (i = 0; i < g_n; i++)            scanf("%d", a + i);      for (i = 0; i < g_n; i++)      {            for (j = 0; j < g_n; j++)            {                  scanf("%d", &t);                  w[(1 << i) | (1 << j)] = 2 * t + a[i] + a[j];            }      }}int work(){      int i, s, res = 0;      bool at[20] = {0};      memset(f, 0, sizeof (f));      for (i = 0; i <= g_k; i++)            at[3 * i] = true;      for (s = 1; s < (1 << g_n); s++)      {            if (at[bcnt[s]])            {                  int b0 = s&-s;                  int s1 = s^b0;                  while (s1)                  {                        int b1 = s1&-s1;                        s1 ^= b1;                        int s2 = s1;                        while (s2)                        {                              int b2 = s2&-s2;                              s2 ^= b2;                              int t = w[b0 | b1] + w[b0 | b2] + w[b1 | b2] + f[s^b0^b1^b2];                              if (f[s] < t)f[s] = t;                        }                  }                  if (res < f[s])res = f[s];            }      }      return res;}int main(){      int s, t;      bcnt[0] = 0;      for (s = 1; s < MAXN; s++)            bcnt[s] = bcnt[s >> 1]+(s & 1);      scanf("%d", &t);      while (t--)      {            reader();            int res = work();            printf("%d\n", res / 2);      }      return 0;}

说实话,很难理解。。。

0 0
原创粉丝点击