ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[折半搜索][has] Jzoj P4250 路径

2019-01-30 19:40:46  阅读:255  来源: 互联网

标签:折半 ll return Jzoj int mo Ai P4250 城市


Description

A国有n个城市,编号为1到n,任意两个城市之间有一条路。shlw闲得没事干想周游A国,及从城市1出发,经过且仅经过除城市1外的每个城市1次(城市1两次),最后回到城市1。由于shlw很傻,他只愿意走一定长度,多了少了都不干,现在他想知道一共有多少种方案可供选择。
 

Input

第一行为两个整数n,l,分别为城市数和路程总长。
之后n行,每行n个整数,其中第i行第j列为Ai,j,满足Ai,i=0;Ai,j=Aj,i。

Output

输出共1行,为总方案数。
 

Sample Input

3 6
0 1 3
1 0 2 
3 2 0

Sample Output

2
 

Data Constraint

对于30%,1<=n<=10
对于另外30%,1<=n<=14,1<=l<=30
对于100%,1<=n<=14,1<=Ai,j<=100,000,000,1<=l<=2,000,000,000
悄悄告诉你:数据的答案都很大,反正直接输0是没分的,但都在int范围内。
为了降低题目难度,Ai,j的种类数不会太多

 

题解

  • 题目大意:有n个城市,问每个城市都走一遍,路径长度刚好为L的方案数
  • 30%,暴力乱搜就好了,O(n!)
  • 60%,n<=14,状压dp,设f[i][j][k]表示当前经过的点的状态为i,现在在点j,当前路径长为k,O(2^n*n^2*30),听说加个map可以跑70分
  • 100%,n<=14,折半搜索可以过
  • 记前半段除了1与i长度为n1,后半段为n2,那么如果确定了i,只要满足前半段与后半段经过的点不重复且路径总长为l就可以计算答案了
  • 具体来说就是就是枚举一个点i,枚举前半段的所有情况,用hash记下来,再枚举后半段的所有情况
  • 并在hash中找到与之对应的前半段,统计进答案中就好了

代码

 

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <cstring>
 4 #define mo 19260817
 5 #define ll long long
 6 #define N 15
 7 using namespace std;
 8 int n,m,l,a[N][N],f[mo],ans,i;
 9 ll g[mo];
10 ll calc(int x,int y,int k){ return x*32768000000000ll+y*2000000000ll+k; }
11 int gethash(int x,int y,int k)
12 {
13     ll r=calc(x,y,k);
14     for (i=r%mo;g[i]&&g[i]!=r;++i==mo?i=0:i);
15     return i;
16 }
17 void dfs1(int d,int x,int y,int k)
18 {
19     if (x&&k>=l) return;
20     if (d>=m)
21     {
22         int p=gethash(x,y,k);
23         g[p]=calc(x,y,k),f[p]++; return;
24     }
25     for (int i=1;i<n;i++) if (!(y>>i&1)) dfs1(d+1,i,y|1<<i,k+a[x][i]);
26 }
27 void dfs2(int d,int x,int y,int k)
28 {
29     if (x&&k>=l) return;
30     if (d>=m)
31     {
32         int p=gethash(x,((~y)&((1<<n)-1))|1|1<<x,l-k);
33         ans+=f[p]; return;
34     }
35     for (int i=1;i<n;i++) if (!(y>>i&1)) dfs2(d+1,i,y|1<<i,k+a[x][i]);
36 }
37 int main()
38 {
39     scanf("%d%d",&n,&l);
40     for (int i=0;i<n;i++) for (int j=0;j<n;j++) scanf("%d",&a[i][j]);
41     m=n/2,dfs1(0,0,1,0),m=n-m,dfs2(0,0,1,0),printf("%d",ans);
42 }

 

标签:折半,ll,return,Jzoj,int,mo,Ai,P4250,城市
来源: https://www.cnblogs.com/Comfortable/p/10339544.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有