2019牛客暑期多校训练营(第二场) - F - Partition problem - 枚举
https://ac.nowcoder.com/acm/contest/882/F
潘哥的代码才卡过去了,自己写的都卡不过去,估计跟评测机有关。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=30;
int g[maxn][maxn],n;
ll ans;
inline void dfs(int mask,int last,int dep,ll sum)
{
if(!dep){
if(sum>ans) ans=sum;
return;
}
if(n-last-1<dep) return;
for(int i=last+1;i<n;++i){
ll tmp=sum;
for(int j=0;j<n;++j){
if(mask>>j&1) tmp-=g[i][j];
else tmp+=g[i][j];
}
dfs(mask|(1<<i),i,dep-1,tmp);
}
return;
}
int main()
{
#ifdef local
freopen("a.txt","r",stdin);
#endif // local
scanf("%d",&n);
n<<=1;
for(int i=0;i<n;++i){
for(int j=0;j<n;++j){
scanf("%d",&g[i][j]);
}
}
ll sum=0;
for(int i=1;i<n;++i) sum+=g[0][i];
dfs(1,0,n/2-1,sum);
printf("%lld\n",ans);
return 0;
}
应该最卡常的思路是折一半,2^14预处理前半部分内部的贡献,再一次预处理后半部分内部的贡献。
答案当然就是,前半部分选了i个1,后半部分选n-i个1的,那么考虑他们合并在一起的新的影响。
暴力的话当然是前半部分的每个1对后半部分的每个0匹配一次。然后后半部分的每个1对前半部分的0匹配一次。
复杂度的话,每种组合实际上都要遍历到,\(C_{2n}^n\) 少不了了。但是每次合并只和1的数量有关。所以需要预处理的时候把“前半部分的该状态的0对后半部分的某个1的贡献”也搞出来。
理论上比这个搜索快多的。这个是咖啡鸡的代码的注释版:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll s[1 << 14], t[1 << 14], p[14], q[14], ret, ans;
int c[30][30], n, d[1 << 14];
//枚举t状态
void dfs(int step, int w, int mask, ll sum) {
//对后半部分搜索完毕
if(step == n) {
ret = max(ret, sum + t[mask]);
return;
}
//选择的人没满,后半部分可以再选一个
if(w < n)
//这一次step选1,也就是后半部分的第step位选1,后半部分第step个选1那当然要加step
dfs(step + 1, w + 1, mask | (1 << step), sum + p[step]);
//等价于n-step+w>n,也就是剩下的人+已选的人超过需要选的人,那么这一步可以选0
if(w > step)
dfs(step + 1, w, mask, sum + q[step]);
}
int main() {
#ifdef Yinku
freopen("Yinku.in", "r", stdin);
#endif // Yinku
scanf("%d", &n);
//d[i]表示i状态有多少个1,用于连接两个集合使用
d[0] = 0;
for(int i = 1; i < (1 << n); i++)
d[i] = d[i / 2] + i % 2;
for(int i = 0; i < n * 2; i++)
for(int j = 0; j < n * 2; j++)
scanf("%d", &c[i][j]);
//折半枚举
//s[i]表示前半部分内部的贡献,t[i]表示后半部分内部的贡献
for(int i = 0; i < (1 << n); i++) {
for(int j = 0; j < n; j++)
if(!(i & (1 << j)))
for(int k = j + 1; k < n; k++)
if(i & (1 << k))
s[i] += c[j][k], t[i] += c[j + n][k + n];
for(int j = 0; j < n; j++)
if(i & (1 << j))
for(int k = j + 1; k < n; k++)
if(!(i & (1 << k)))
s[i] += c[j][k], t[i] += c[j + n][k + n];
}
//折半枚举
//p[k]表示当前前半部分为i状态,后半部分的第k个为1的时候的对前半部分的所有的0产生的贡献
//q[k]表示当前前半部分为i状态,后半部分的第k个为0的时候的对前半部分的所有的1产生的贡献
for(int i = 0; i < (1 << n); i++) {
for(int k = 0; k < n; k++)
p[k] = 0, q[k] = 0;
for(int j = 0; j < n; j++) {
if(!(i & (1 << j)))
for(int k = 0; k < n; k++)
p[k] += c[j][k + n];
else
for(int k = 0; k < n; k++)
q[k] += c[j][k + n];
}
ret = 0;
//前半部分为i状态,它拥有d[i]个已选择的人
dfs(0, d[i], 0, 0);
//把前半部分的s[i]状态加进去
ans = max(ans, ret + s[i]);
}
printf("%lld\n", ans);
}
2019牛客暑期多校训练营(第二场) - F - Partition problem - 枚举的更多相关文章
- 2019牛客暑期多校训练营(第二场) H-Second Large Rectangle(单调栈)
题意:给出由01组成的矩阵,求求全是1的次大子矩阵. 思路: 单调栈 全是1的最大子矩阵的变形,不能直接把所有的面积存起来然后排序取第二大的,因为次大子矩阵可能在最大子矩阵里面,比如: 1 0 0 1 ...
- 2019 牛客暑期多校 第三场 F Planting Trees (单调队列+尺取)
题目:https://ac.nowcoder.com/acm/contest/883/F 题意:求一个矩阵最大面积,这个矩阵的要求是矩阵内最小值与最大值差值<=m 思路:首先我们仔细观察范围,我 ...
- 2020牛客暑期多校训练营 第二场 K Keyboard Free 积分 期望 数学
LINK:Keyboard Free 我要是会正经的做法 就有鬼了. 我的数学水平没那么高. 三个同心圆 三个动点 求围成三角形面积的期望. 不会告辞. 其实可以\(n^2\)枚举角度然后算出面积 近 ...
- 2020牛客暑期多校训练营 第二场 J Just Shuffle 置换 群论
LINK:Just Shuffle 比较怂群论 因为没怎么学过 置换也是刚理解. 这道题是 已知一个置换\(A\)求一个置换P 两个置换的关键为\(P^k=A\) 且k是一个大质数. 做法是李指导教我 ...
- 2020牛客暑期多校训练营 第二场 I Interval 最大流 最小割 平面图对偶图转最短路
LINK:Interval 赛时连题目都没看. 观察n的范围不大不小 而且建图明显 考虑跑最大流最小割. 图有点稠密dinic不太行. 一个常见的trick就是对偶图转最短路. 建图有点复杂 不过建完 ...
- 2020牛客暑期多校训练营 第二场 C Cover the Tree 构造 贪心
LINK:Cover the Tree 最受挫的是这道题,以为很简单 当时什么都想不清楚. 先胡了一个树的直径乱搞的贪心 一直过不去.后来意识到这类似于最经典长链剖分优化贪心的做法 然后那个是求最大值 ...
- 2020牛客暑期多校训练营 第二场 B Boundary 计算几何 圆 已知三点求圆心
LINK:Boundary 计算几何确实是弱项 因为好多东西都不太会求 没有到很精通的地步. 做法很多,先说官方题解 其实就是枚举一个点 P 然后可以发现 再枚举一个点 然后再判断有多少个点在圆上显然 ...
- 2020牛客暑期多校训练营 第二场 A All with Pairs 字符串hash KMP
LINK:All with Pairs 那天下午打这个东西的时候状态极差 推这个东西都推了1个多小时 (比赛是中午考试的我很困 没睡觉直接开肝果然不爽 一开始看错匹配的位置了 以为是\(1-l\)和\ ...
- 2019牛客暑期多校训练营(第九场) D Knapsack Cryptosystem
题目 题意: 给你n(最大36)个数,让你从这n个数里面找出来一些数,使这些数的和等于s(题目输入),用到的数输出1,没有用到的数输出0 例如:3 4 2 3 4 输出:0 0 1 题解: 认真想一 ...
- 2019牛客暑期多校训练营(第五场)G - subsequeue 1 (一题我真的不会的题)
layout: post title: 2019牛客暑期多校训练营(第五场)G - subsequeue 1 (一题我真的不会的题) author: "luowentaoaa" c ...
随机推荐
- VirtualBox中安装CentOS 7后无法上网问题
1.在VirtualBox的设置界面,点击“网络”, 将虚拟机的“连接方式”设置为桥接模式, “界面名称”选择笔记本的无线网卡(一般是“wireless Network”的选项) 将“接入网线”勾选上 ...
- Java基础学习(3)
Java基础学习(三) Java异常 Throwable类:所有异常的祖先类 Error:虚拟机异常.内存错误.没法处理 Exception:编码.环境.用户操作输入出现问题 非检查异常(自动捕获): ...
- ffmpeg知多少~~~
一.ffmpeg安装: https://jingyan.baidu.com/article/f7ff0bfcd64cea2e26bb1334.html 二.ffmpeg视频处理(包括各种视频流处理 ...
- js 一个不得不注意的浏览器兼容性问题 进制转换
写几行JS代码 var num = '022'; alert(num+' '+parseInt(num)+' '+parseInt(num,10)); 不同的浏览器将会得到不同的结果在谷歌浏览器下的结 ...
- 十大热门AI芯片
资料来源:头条<人工智能影响力报告>中的人工智能十大热门芯片 iPhone X内部搭载了一颗全新定制的处理器——A11 Boinic,用来承担人脸识别和移动支付的工作负荷.双核心A11芯片 ...
- python-验证功能的装饰器示例
user_list=[ {'}, {'}, {'} ] current_dict={'username':None,'login':False} def auth(auth_type): def au ...
- python基础--6 集合
#1.不同元素组成#2.无序#3.集合中的元素必须为不可变类型 a={1,2,3,4,5,(1,2,3)}print(a) #随机向集合添加元素a.add("sjsj")print ...
- python3 使用 django-xadmin 遇到的许多坑
几乎所有公司项目都是python2的, xadmin对Python2 很友好,对Python3 很不友好, 所以在Python3 环境下使用xadmin遇到了许多意想不到的坑,在这里记录并分享一下: ...
- LeetCode--043--字符串相乘(java)
给定两个以字符串形式表示的非负整数 num1 和 num2,返回 num1 和 num2 的乘积,它们的乘积也表示为字符串形式. 示例 1: 输入: num1 = "2", num ...
- 2017ICPC沈阳网络赛 HDU 6201 -- transaction transaction transaction(树上dp)
transaction transaction transaction Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 132768/1 ...