jzoj 1769 islands and bridge
来源:互联网 发布:程序员面试宝典5下载 编辑:程序博客网 时间:2024/06/05 15:42
Description
给定一些岛屿和一些连接岛屿的桥梁,大家都知道汉密尔顿路是访问每个岛屿一次的路线,在我们这个地图中,每个岛屿有个正整数的权值,表示这个岛屿的观赏价值。假设一共有N个岛屿,用Vi表示岛屿Ci的价值,汉密尔顿路C1C2….Cn的价值是以下三部分的总和:
(1)所有岛屿的价值之和;
(2)对于路径中相邻的两个岛屿CiCi+1,把两个岛屿的价值之积加到总价值中;
(3)路径中连续三个岛屿CiCi+1Ci+2,如果Ci与Ci+2有桥直接相连,则把这三个岛屿价值之积加到总价值中。
要求计算汉密尔顿路最大的价值以及方案数。
Input
输入第一行是一个整数Q(Q<=20),表示测试数据的数量。每个测试数据第一行输入两个整数N和M,分别表示岛屿数和桥梁数,接下来一行包含N个正整数,第i个数表示Vi,每个数不超过100,最后M行,每行两个数X,Y,表示岛X和岛Y之间有一座桥直接相连,桥是双向的,岛屿编号为1到N(N<=13)
Output
对于每个测试数据,输出一行,两个整数,第一个数表示最大价值,第二个数表示方案数,如果不存在汉密尔顿路径,输出“0 0”
注意:一条路径可以反着走,我们认为这两条路径是同一条路径。
Sample Input
2
3 3
2 2 2
1 2
2 3
3 1
4 6
1 2 3 4
1 2
1 3
1 4
2 3
2 4
3 4
Sample Output
22 3
69 1
Solution
不太熟悉c++的pascal选手表示心态爆炸。
一直有各种运算优先级的差异导致疯狂调试,终极爆炸。
状压专题*2
考虑定义一个状态f[i][j][k]
i为一个二进制状态,0,1表示选了或者没选,j,k则表示上两次所选的编号。
预处理一下f数组
考虑转移 很显然
枚举一个t f[i|(1<<(t-1))][k][t]=max(f[i][j][k]+a[t]+a[t]*a[k]+a[t]*a[k]*a[j](j,t相连))
调了很久很烦 下定决心掌握调试技巧
Code
```#include <cstdio>#include <cstring>#include <algorithm>#define fo(i,a,b) for (i=a;i<=b;i++)#define ll long longusing namespace std;ll map[25][25];ll f[9000][13][13],cnt[9000][13][13],a[20];int main(){ ll n,m,x,y,q,s,tt,h; int i,j,k,t; freopen("1.in","r",stdin); freopen("1.out","w",stdout); scanf("%lld",&tt); while (tt) { tt--; scanf("%lld%lld",&n,&m); memset(map,0,sizeof(map)); memset(f,0,sizeof(f)); memset(cnt,0,sizeof(cnt)); fo(i,1,n) scanf("%lld",&a[i]); if (n==1) { printf("%lld ",a[1]); printf("1\n"); continue; } fo(i,1,m) { scanf("%lld%lld",&x,&y); map[x][y]=1,map[y][x]=1; } q=(1<<n)-1; for (j=1;j<=n;j++) for (k=1;k<=n;k++) { if (j==k||!map[j][k]) continue; x=1<<(j-1),y=1<<(k-1); f[(x|y)][j][k]=a[k]*a[j]+a[k]+a[j]; cnt[(x|y)][j][k]=1; } fo(i,1,q) { for (j=1;j<=n;j++) { if ((i&(1<<(j-1)))==0) continue; for (k=1;k<=n;k++) { if ((!map[j][k])||(f[i][j][k]==0)) continue; for (t=1;t<=n;t++) { if ((!map[k][t])||((i&(1<<(t-1)))!=0)) continue; //if ((i|(1<<(t-1)))>q) continue; if (map[j][t]) s=a[j]*a[k]*a[t]; else s=0; if (f[i+(1<<(t-1))][k][t]==(f[i][j][k]+s+a[t]+a[t]*a[k])) cnt[i+(1<<(t-1))][k][t]+=cnt[i][j][k]; else if (f[i+(1<<(t-1))][k][t]<(f[i][j][k]+s+a[t]+a[t]*a[k])) cnt[i+(1<<(t-1))][k][t]=cnt[i][j][k]; f[i+(1<<(t-1))][k][t]=max(f[i+(1<<(t-1))][k][t],f[i][j][k]+s+a[t]+a[t]*a[k]); // cnt[i|(1<<(t-1))][j][k]=cnt[i][j][k]+h+cnt[i|(1<<(t-1))][j][k]; } } } } ll p=0; ll ans=0; for (i=1;i<=n;i++) for (j=1;j<=n;j++) if (i!=j) { // q=(1<<(j-1))|(1<<(i-1)); if (p<f[q][i][j]) { p=f[q][i][j]; ans=cnt[q][i][j]; } else if (p==f[q][i][j]) ans+=cnt[q][i][j]; } if (p==0) { printf("0 0\n"); continue; } printf("%lld ",p); printf("%lld\n",(ans/2)); }}
(我的代码还是很丑呀)
- jzoj 1769 islands and bridge
- JZOJ 1769 Islands and Bridges
- JZOJ 1769.Islands and Bridges
- (状态压缩) Islands and Bridge (P2288)
- POJ 2288 Islands and Bridge 状压DP
- POJ3608-Bridge Across Islands
- 【poj3608】 Bridge Across Islands
- poj3608 Bridge Across Islands
- Bridge Across Islands POJ
- poj 3608 Bridge Across Islands
- 【POJ 3608】Bridge Across Islands
- POJ 3608 Bridge Across Islands
- POJ 3608 Bridge Across Islands
- poj 3608 Bridge Across Islands 凸包最短距离
- POJ 3608 Bridge Across Islands(旋转卡壳)
- POJ 3608 Bridge Across Islands 已翻译
- POJ:3608 Bridge Across Islands 旋转卡壳
- [pku2288]Islands and Bridges
- OpenAI Gym4
- 判断浏览器是否用微信访问
- Javaweb中的cookie与session
- Emacs搭建开发环境(ECB+Cedet)
- Python语言入门(一)字符串操作
- jzoj 1769 islands and bridge
- 小波变换教程(九)
- HTTP请求报文和响应报文
- "java文件-class文件-JVM显示" 编码执行过程
- 第四章 Greenplum环境变量
- 3.7 for语句与数组
- 12.矩形覆盖
- css3、jq、js三种方法实现逐渐消失
- git reset push