USCoj 1396- Select Team 状压DP
来源:互联网 发布:淘宝多琳香水是正品么 编辑:程序博客网 时间:2024/06/05 07:20
要做这道题我推荐先做一下我记录的上一道题
http://blog.csdn.net/q610376681/article/details/51330654
看懂了那道题再做这个就简单一点了
题目链接:
http://61.187.179.71:9988/problem.php?id=1396
题目大意:给你n个人,每一个人都有一个能力值,要选出k支队伍,每支队伍三个人,一个队伍中任意两个人配合会能力值加成,能力值加成以一个n*n的矩阵给出,问选出的k队伍能力值加起来最大是多少
解题思路:
考虑状压dp
假设一共有10人 要选出2支队伍
1代表选某个人 0代表没有
某一个状态为 s=1 0 1 0 1 0 1 0 1 1
1 2 3 4 5 6 7 8 9 10
最优解恰好在这个状态里 为 1 3 10与5 7 9组队,我们只需枚举某一个状态里存在的任意三个人组队的能力值,以及剩下的所有人的能力值加成就可以了
比如这个例子 要枚举 i=0 0 0 0 0 0 1 0 1 1 和剩下的s-i
i=0 0 0 0 1 0 0 0 1 1 和剩下的s-i
i=0 0 1 0 0 0 0 0 1 1 和剩下的s-i
…… …
i=1 0 1 0 1 0 0 0 0 0 和剩下的s-i
总之转移就是挑出一个状态s里的任意三个人组成一个队状态为i,剩下的人组成一个队,找出它们的最大值即可
dp[s]=max(dp[s],team[i]+dp[s-i]);
team就是三个人组成一队的能力值,dp[s-i]就是剩下的人组成的能力值。
因为时限卡的很紧,有两个方面要注意:
1.当状态s里1的个数为3的整数倍的时候再进行转移
2.枚举状态s里的任意三个人组成一队的时候,不需要枚举所有的三个人,只需要枚举最后一个1,和其后所有2个1的排列组合即可,因为,前面为三个1的情况我们已经计算过了
#include <iostream>#include <cstring>#include <cstdio>#include <cstdlib>#include <cmath>#include <string>#include <vector>#include <list>#include <map>#include <queue>#include <stack>#include <algorithm>#include <numeric>#include <functional>#define RI(N) scanf("%d",&(N))#define RII(N,M) scanf("%d %d",&(N),&(M))#define RIII(N,M,K) scanf("%d %d %d",&(N),&(M),&(K))#define mem(a) memset((a),0,sizeof(a))using namespace std;const int inf=1e9;const int inf1=-1*1e9;double EPS=1e-10;int k,n;typedef long long LL;int b[25][25];int a[25];int dp[1<<18];int tt[1<<18];int call[1<<18];int tem[20];int cal(int s){ int s1=s; if(call[s]>=0) return call[s]; int x=0; while(s) { x++; s&=(s-1); } return call[s1]=x;}int main(){ int t; RI(t); memset(call,-1,sizeof(call)); while(t--) { RII(k,n); for(int i=0; i<n; i++) RI(a[i]); for(int i=0; i<n; i++) for(int j=0; j<n; j++) RI(b[i][j]); memset(dp,0,sizeof(dp)); for(int i=0; i<n; i++) for(int j=i+1; j<n; j++) for(int k=j+1; k<n; k++) { int y=1<<i|1<<j|1<<k; tt[y]=a[i]+a[j]+a[k]+b[i][j]+b[j][k]+b[i][k]; } int anss=0; k*=3; for(int i=1; i<(1<<n); i++) { if(cal(i)%3==0) { int poi=0; for(int j=0; j<n; j++) { if(i>>j&1) tem[poi++]=j; } int x=1<<tem[poi-1]; for(int j=0; j<poi-1; j++) for(int k=j+1; k<poi-1; k++) { int y=(1<<tem[j])|(1<<tem[k])|x; dp[i]=max(dp[i],tt[y]+dp[i-y]); } if(call[i]==k) anss=max(anss,dp[i]); } } printf("%d\n",anss); } return 0;}
- USCoj 1396- Select Team 状压DP
- [dp]1396:Select Team
- bzoj1722 [Usaco2006 Mar] Milk Team Select 产奶比赛(树形dp)
- USCOJ 1082: 数字统计
- USCOJ 1072: 迷宫
- 图论+dp poj 1112 Team Them Up!
- POJ 1112 Team Them Up! DP
- ZOJ 3872 - Team Formation(DP)
- USCOJ 1067: 笨小猴(monkey)
- USCOJ 1102 机器翻译(translate)
- Team
- Team
- 【iOS】Signing for requires a development team. Select a development team in the project editor. Code
- Signing for requires a development team. Select a development team in the project editor. Code
- Signing for "xxx" requires a development team. Select a development team
- ios Signing for "" requires a development team. Select a development team in the project editor.
- Signing for requires a development team. Select a development team in the project editor. Code
- USACO MAR 2006 Milk Team Select(产奶比赛)
- Memcache 基础教程(php 缓存)
- swift 新闻列表实现
- C#二十四 Ado.Net简介
- java 回调
- 模拟实现strrchr,strchr
- USCoj 1396- Select Team 状压DP
- __typeof在Xcode7中的使用
- int 等数据类型的含义
- A. Holidays
- 推荐几个常用的Git代码托管平台
- 机器学习简介
- 【会议】QCon2016会议整理(一)——工程效率与架构
- Problem3-1001
- Android源码浅析(二)——Ubuntu Root,Git,VMware Tools,安装输入法,主题美化,Dock,安装JDK和配置环境