POJ 2288 Islands and Bridges
2016-04-19 19:38
423 查看
题目链接: http://poj.org/problem?id=2288
题意:给出一个图,每个点都有权值,有一些边连接着这些点,现在定义一条哈密顿回路产生的值为以下三者之和:1、回路上的各个点的权值之和 2、回路中相邻点的乘积之和 3、如果回路中有c1c2c3,且c1与c3也相邻,那么就加上c1*c2*c3。现在求一共有多少条回路产生的值可以同时达到最大。
思路:状态压缩DP,因为考虑到第三个值,所以我们需要记录一个状态的当前所在点和上一个所在点。然后就可以转移了,至于路径数量,我们可以再开一个数组,更新答案时顺带着一起更新即可。
题意:给出一个图,每个点都有权值,有一些边连接着这些点,现在定义一条哈密顿回路产生的值为以下三者之和:1、回路上的各个点的权值之和 2、回路中相邻点的乘积之和 3、如果回路中有c1c2c3,且c1与c3也相邻,那么就加上c1*c2*c3。现在求一共有多少条回路产生的值可以同时达到最大。
思路:状态压缩DP,因为考虑到第三个值,所以我们需要记录一个状态的当前所在点和上一个所在点。然后就可以转移了,至于路径数量,我们可以再开一个数组,更新答案时顺带着一起更新即可。
#include <cstdio> #include <cmath> #include <cstring> #include <string> #include <cstdlib> #include <iostream> #include <algorithm> #include <stack> #include <map> #include <set> #include <vector> #include <sstream> #include <queue> #include <utility> using namespace std; #define rep(i,j,k) for (int i=j;i<=k;i++) #define Rrep(i,j,k) for (int i=j;i>=k;i--) #define Clean(x,y) memset(x,y,sizeof(x)) #define LL long long #define ULL unsigned long long #define inf 0x7fffffff #define mod %100000007 const int maxn = 14; bool a[maxn][maxn]; int v[maxn]; LL dp[1<<13][maxn][maxn]; LL cal[1<<13][maxn][maxn]; int tri[maxn][maxn][maxn]; int ans; int T; int n,m; int main() { cin>>T; while(T--) { ans = 0; scanf("%d%d",&n,&m); rep(i,1,n) { scanf("%d",&v[i]); ans+=v[i]; //先将每个点的权值都算出来,最后再加上。 } Clean(a,false); rep(i,1,m) { int tx,ty; scanf("%d%d",&tx,&ty); a[tx][ty] = true; a[ty][tx] = true; } if ( n == 1 ) { printf("%d %d\n",v[1],1); continue; } Clean(dp,-1); Clean(cal,0); rep(i,1,n-1) //预处理初始状态,只走过两个点的情况 rep(j,i+1,n) if ( i != j && a[i][j] ) { int a = 1<<(i-1); int b = 1<<(j-1); dp[a+b][i][j] = v[i]*v[j]; dp[a+b][j][i] = v[i]*v[j]; cal[a+b][i][j] = 1; cal[a+b][j][i] = 1; } Clean(tri,0); rep(i,1,n) rep(j,1,n) rep(k,1,n) if ( i != j && j != k && k != i && a[i][j] && a[j][k] && a[k][i] ) tri[i][j][k] = tri[j][k][i] = tri[k][i][j] = v[i]*v[j]*v[k]; int uplim = 1<<n; rep(i,1,uplim-1) // 枚举状态 { rep(j,1,n) //枚举当前状态的最后一个节点 if ( i & 1<<(j-1) ) //状态存在该点 { int last = i & ~(1<<(j-1)); //上一个状态 if ( last == 0 ) break; rep(k,1,n) //枚举上个节点 { if ( !a[k][j] || !(last & 1<<(k-1)) ) continue; rep(l,1,n) { if ( l == j || !a[k][l] || !(i & 1<<(l-1)) ) continue; if ( dp[last][k][l] == -1 ) continue; LL temp = dp[last][k][l] + v[j]*v[k] + tri[j][k][l]; if ( dp[i][j][k] == temp ) cal[i][j][k] += cal[last][k][l]; else if ( dp[i][j][k] < temp ) { dp[i][j][k] = temp; cal[i][j][k] = cal[last][k][l]; } } } } } LL m = 0; LL tot = 0; rep(i,1,n) rep(j,1,n) if ( dp[uplim-1][i][j] > m ) { m = dp[uplim-1][i][j]; tot = cal[uplim-1][i][j]; } else if ( dp[uplim-1][i][j] == m ) tot+=cal[uplim-1][i][j]; if ( tot != 0 ) m+=ans; printf( "%I64d %I64d\n" , m, tot>>1 ); } return 0; }
相关文章推荐
- 数据结构和算法15 之二叉树排序
- LeetCode Sum Root to Leaf Numbers
- struts2的工作原理和相关文件的介绍
- 软件项目管理(二)——用jenkins持续集成、Maven、Github的使用
- androidstudio 问题
- hihoCoder--1268--九宫(全排列)
- js设置form的onsubmit事件
- 第八周项目4游戏中的角色类增强版
- 保姆照顾小孩的五种实现:常规、代理协议、Block、观察者、通知
- 多个C3P0的java举例
- HDFS副本放置策略
- 设计模式(6)之建造者模式
- 华为二面---华丽的扑街
- exmail 清空队列中某个用户邮件
- hiho 35 二分图三·二分图最小点覆盖和最大独立集
- Linux系统启动引导过程和服务控制
- 第八周实践项目3-指向学生类的指针
- poj 1062 昂贵的婚礼 djkstra
- JavaScript中的运算符(1)
- 237.[LeetCode]Delete Node in Linked List