POJ 2531 Network Saboteur(暴力美学)
2015-11-30 00:44
232 查看
最近心情不好,而且今天已经wa到哭了,感觉特别悲催!感觉自己的这题的思路还不错,必须来写写博客释放下自己的情绪。
题目大意:有N个节点(0~N-1),给一个邻接矩阵,Cij代表节点i到节点j的花费,其中Cii == 0, Cij == Cji。需要把所有的节点分成A,B两部分,其中的花费就是 ∑Cij (i∈A,j∈B),求最大的花费。(2 <= N <= 20)
解题思路:上午做题的时候没有什么好的思路,但是也想到了怎样去枚举。就是直接用整数来表示集合,那么转换成2进制,如果第i位是0,就表示第i个节点在A集合,否则在B集合。我们来分析下时间复杂度,集合的个数最多是1 << 20,大概是10的6次方多一点,感觉这个时间怎么也不能再少了,然后对于每一个集合,我们的计算大概是N * N,那么这个时间复杂度怎么也通不过。但是,我们仔细思考,如果我们可以把 N * N降成N,那么这道题目大概就能AC了。那么要怎么降低这个时间复杂度呢?其实感觉有点像动态规划或者递推的思想,那就是我们可以保存一下前面的状态,由前面的已经求过的状态通过一个O(N)的复杂度直接推过来。那么问题就迎刃而解了。至于究竟是怎么推的,我已经在代码里面加好注释了,因为涉及到位操作,在这里可能讲不清楚。
Show me the code!
题目大意:有N个节点(0~N-1),给一个邻接矩阵,Cij代表节点i到节点j的花费,其中Cii == 0, Cij == Cji。需要把所有的节点分成A,B两部分,其中的花费就是 ∑Cij (i∈A,j∈B),求最大的花费。(2 <= N <= 20)
解题思路:上午做题的时候没有什么好的思路,但是也想到了怎样去枚举。就是直接用整数来表示集合,那么转换成2进制,如果第i位是0,就表示第i个节点在A集合,否则在B集合。我们来分析下时间复杂度,集合的个数最多是1 << 20,大概是10的6次方多一点,感觉这个时间怎么也不能再少了,然后对于每一个集合,我们的计算大概是N * N,那么这个时间复杂度怎么也通不过。但是,我们仔细思考,如果我们可以把 N * N降成N,那么这道题目大概就能AC了。那么要怎么降低这个时间复杂度呢?其实感觉有点像动态规划或者递推的思想,那就是我们可以保存一下前面的状态,由前面的已经求过的状态通过一个O(N)的复杂度直接推过来。那么问题就迎刃而解了。至于究竟是怎么推的,我已经在代码里面加好注释了,因为涉及到位操作,在这里可能讲不清楚。
Show me the code!
#include <cstdio> using namespace std; int N, cost[20][20], s[1 << 20], ans = 0; int main() { scanf("%d", &N); for (int i = 0; i < N; ++i) { for (int j = 0; j < N; ++j) { scanf("%d", &cost[i][j]); } } for (int i = 1; i < 1 << N; ++i) { int t1 = 0, t2 = 0, j = i - (i & -i);//j = i 去掉二进制中最低位的1 for (int k = 0; k < N; ++k) {//k 是 i 比 j 多的那一位所对应的节点 for (int l = 0; i - j >> k & 1 && l < N; ++l) { //这里嵌套了两个for, 可是内层for只会执行一次, 所以是O(N)的 if (j >> l & 1) t1 += cost[k][l]; //t1 = 把第k个节点从一个集合移到另一个集合所减少的花费 else t2 += cost[k][l]; //t2 = 把第k个节点从一个集合转移到另一个集合所增加的花费 } } //s[i] <<==== s[j] s[i] = s[j] - t1 + t2; ans = ans > s[i] ? ans : s[i]; } printf("%d\n", ans); return 0; }
相关文章推荐
- 枚举的用法详细总结
- c#入门之枚举和结构体使用详解(控制台接收字符串以相反的方向输出)
- 理解C#中的枚举(简明易懂)
- C#枚举中的位运算权限分配浅谈
- C++基础入门教程(四):枚举和指针
- FileShare枚举的使用小结(文件读写锁)
- Java枚举类用法实例
- 枚举窗口句柄后关闭所有窗口示例
- javascript模拟枚举的简单实例
- 深入剖析JavaScript中的枚举功能
- 枚举和宏的区别详细解析
- 深入理解C#中的枚举
- C#实现获取枚举中元素个数的方法
- java中枚举的详细使用介绍
- java枚举的使用示例
- Java枚举详解及使用实例(涵盖了所有典型用法)
- 深入解析Swift编程中枚举类型的相关使用
- 一个运用enum类型的Demo
- 枚举隐式派生于System.Enum
- 枚举的隐士转换跟显示转换