2019牛客多校第二场F-Partition problem(搜索+剪枝)
2024-08-29 22:52:15
Partition problem
解题思路
假设当前两队的对抗值为s,如果把红队中的一个人a分配到白队,s+= a对红队中所有人的对抗值,s-= a对白队中所有人的对抗值。所以我们可以先假设所有人都在红队中,把人一个一个分配到白队中,枚举所有的情况求最大值。
然后继续剪枝:
1.我们可以让1是固定在白队。
2.在搜索的过程中让序号递增,以此来避免重复枚举。
3.保证剩下的的人数足够选择,不够的必然不行。
代码如下
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
inline int read(){
int res = 0, w = 0; char ch = 0;
while(!isdigit(ch)){
w |= ch == '-', ch = getchar();
}
while(isdigit(ch)){
res = (res << 3) + (res << 1) + (ch ^ 48);
ch = getchar();
}
return w ? -res : res;
}
const int N = 30;
ll a[N][N];
bool in[N];
ll ans;
int n;
void dfs(int x, int c, ll sum)
{
if(c == n){ //已经选择了n个人到白队
ans = max(ans, sum);
return;
}
for(int i = x + 1; i <= n + c + 1; i ++){ //保证剩下的够选
ll temp = sum;
for(int j = 1; j <= 2 * n; j ++){
if(in[j])
sum -= a[i][j];
else
sum += a[i][j];
}
in[i] = true;
dfs(i, c + 1, sum);
in[i] = false; //回溯
sum = temp;
}
}
int main()
{
cin >> n;
for(int i = 1; i <= 2 * n; i ++){
for(int j = 1; j <= 2 * n; j ++){
a[i][j] = read();
}
}
ll sum = 0;
in[1] = true; //1固定在白队
for(int i = 2; i <= 2 * n; i ++)
sum += a[1][i];
dfs(1, 1, sum);
cout << ans << endl;
return 0;
}
最新文章
- ABP框架 - 日志
- @Column
- 自定义view--实现滑动
- Python描述符(descriptor)解密(转)
- 2015baidu复赛2 连接的管道(mst &;&; 优先队列prim)
- nginx 缓存机制
- js中this和回调方法循环-我们到底能走多远系列(35)
- Boost下载安装编译配置使用指南
- Delphi word 颜色
- .NET基础之自定义泛型
- NEERC 2014, Eastern subregional contest
- 【BZOJ1042】【DP + 容斥】[HAOI2008]硬币购物
- 3--OC -- 点语法
- Android编程之SparseArray<;E>;详解
- GOLang(数组操作随篇)
- 简述在ADO中使用接口的抽象数据提供程序以及ADO.NET数据提供程序工厂模型
- 修改 Vultr 登录密码
- git 命令(提高篇)的本质理解
- 解决linux下“XX不在 sudoers 文件中。此事将被报告";的问题
- TZOJ 3711 浪漫自习(最大流)
热门文章
- window下搭建qt开发环境编译、引用ace
- 编译 Qt 5.6(使QtWebEngine支持XP)
- 如何在Qt中处理(接收/发送)MFC或Windows消息(直接覆盖MainDialog::nativeEvent,或者QApplication::installNativeEventFilter安装过滤器,或者直接改写QApplication::nativeEventFilter)
- APP导航设计九法
- SpringCloud-分布式配置中心【加密-对称加密】
- Android WebView设置背景透明
- 升级vue全家桶过程记录
- wince kill 进程
- Spark学习之路(一)—— Spark简介
- C++学习笔记 之 运算符