hdu 4026 2011上海赛区网络赛F TSP ****

没看过TSP,先mark

  1 //4838039 2011-10-27 23:04:15 Accepted 4026 2343MS 31044K 3143 B C++ Geners
  2 //状态压缩DP的TSP问题
  3 //优先级位运算小于判等 , 还有各种细节各种出错
  4 #include <cstdio>
  5 #include <cstring>
  6 #include <stdlib.h>
  7 #define mabs(a) (a>0?a:-(a))
  8
  9 using namespace std;
 10
 11 typedef long long ll;
 12 const int maxn=1<<17;
 13 int gcd(int a, int b)
 14 {
 15     return b?gcd(b, a%b):a;
 16 }
 17
 18 int g[7][7];
 19 int map[7][7], cnt;
 20 int n, m;
 21 ll dp[maxn][30];
 22 struct Node {
 23     int x,y;
 24 }node[20];
 25
 26 void init ()
 27 {
 28     for (int i=0 ; i<7 ; ++i)
 29         for (int j=0 ; j<7 ; ++j)
 30             g[i][j]=gcd(i, j);
 31 }
 32
 33 bool valid(int sta, int k, int pre)
 34 {
 35     int x=node[k].x,xx=node[pre].x;
 36     int y=node[k].y,yy=node[pre].y;
 37
 38     if(map[x][y]>0 || map[xx][yy]>0)
 39         return false;//如果2个点不都是0。
 40     int d=g[mabs(x-xx)][mabs(y-yy)];
 41     for (int i=1 ; i<=d ; ++i)
 42     {
 43         int tmpx=xx+i*(x-xx)/d;
 44         int tmpy=yy+i*(y-yy)/d;
 45         if(map[tmpx][tmpy] == 1)
 46             return false;//中间点forbidden
 47         if(map[tmpx][tmpy] <= 0)
 48         {
 49             if((sta&(1<<(-map[tmpx][tmpy]))) == 0)
 50             {
 51                 return false;
 52             }//中间有未遍历的0。
 53         }
 54     }
 55     return true;
 56 }
 57
 58 void DP()
 59 {
 60     memset (dp, 0, sizeof(dp));
 61     int limit=1<<cnt;
 62     for (int i=0 ; i<limit ; ++i)
 63     {
 64         for (int j=0 ; j<cnt ; ++j)
 65         {
 66             dp[1<<j][j]=1ll;//初始以每个点开始的情况
 67             if(i&(1<<j))
 68             for (int k=0 ; k<cnt ; ++k)
 69             {
 70                 if(k==j)continue;
 71                 if(i^(1<<j)& (1<<k) )   //k是从此时出发的点,j是要去的点
 72                 if(valid(i,j,k))
 73                 {
 74                         dp[i][j]+=dp[i^(1<<j)][k];
 75                 }
 76             }
 77         }
 78     }
 79     ll ans=0ll;
 80     for (int i=0 ; i<cnt ; ++i)
 81         ans+=dp[limit-1][i];
 82     printf("%I64d\n", ans);
 83
 84 }
 85
 86 int main ()
 87 {
 88     init ();
 89     while (~scanf("%d%d", &n, &m))
 90     {
 91         cnt=0;
 92         for (int i=0 ; i<n ; ++i)
 93         {
 94             for (int j=0 ; j<m ; ++j)
 95             {
 96                 scanf("%d",&map[i][j]);
 97                 if(map[i][j] == 0)
 98                 {
 99                     node[cnt].x=i;
100                     node[cnt].y=j;
101                     map[i][j]=-cnt;//映射到小于等于0
102                     cnt++;
103                 }
104                 //printf(" %d \n",map[i][j]);
105             }
106         }
107         DP();
108     }
109     return 0;
110 }
时间: 2024-12-18 00:31:55

hdu 4026 2011上海赛区网络赛F TSP ****的相关文章

hdu 4025 2011上海赛区网络赛E 压缩 ***

直接T了,居然可以这么剪枝 题解链接:点我 1 #include<cstdio> 2 #include<map> 3 #include<cstring> 4 #define ll __int64 5 using namespace std; 6 ll a[23],x[23][5],ans; 7 map<ll,ll>p; 8 void dfs(int d,int n,ll res,int f) 9 { 10 if(d==n){ 11 if(f) p[res]+

hdu 4041 2011北京赛区网络赛F 组合数+斯特林数 ***

插板法基础知识 斯特林数见百科 1 #include<iostream> 2 #include<cmath> 3 #include<cstdio> 4 #include<cstring> 5 #define LL long long 6 #define eps 1e-7 7 #define MOD 1000000007 8 using namespace std; 9 int c[2001][2001]={1},stir2[1005][1005]={1};

hdu 4036 2011成都赛区网络赛F 模拟 **

为了确保能到达终点,我们需要满足下面两个条件 1.能够到达所有山顶 2.能够在遇到苦土豆时速度大于他 二者的速度可以用能量守恒定律做,苦土豆的坐标可通过三角形相似性来做 #include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<cmath> #include<queue> #include<map> using na

hdu 4023 2011上海赛区网络赛C 贪心+模拟

以为是贪心,结果不是,2333 贪心最后对自己绝对有利的情况 点我 1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #include<queue> 7 #include<map> 8 using namespace std; 9 #define MOD 10000000

hdu 4028 2011上海赛区网络赛H dp+map离散

一开始用搜索直接超时,看题解会的 1 #include<iostream> 2 #include<cstdio> 3 #include<map> 4 #include<cstring> 5 #include<cmath> 6 #include<vector> 7 #include<queue> 8 #include<algorithm> 9 #include<set> 10 #define inf

hdu 4027 2011上海赛区网络赛 线段树 成段平方根 ***

不能直接使用成段增减的那种,因为一段和的平方根不等于平方根的和,直接记录是否为1,是1就不需要更新了 1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #include<queue> 7 #include<map> 8 using namespace std; 9 #de

hdu 4006 优先队列 2011大连赛区网络赛F **

签到题都要想一会 1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #include<queue> 7 #include<map> 8 using namespace std; 9 #define MOD 1000000007 10 const int INF=0x3f3

hdu 4035 2011成都赛区网络赛E 概率dp ****

太吊了,反正我不会 1 /* 2 HDU 4035 3 4 dp求期望的题. 5 题意: 6 有n个房间,由n-1条隧道连通起来,实际上就形成了一棵树, 7 从结点1出发,开始走,在每个结点i都有3种可能: 8 1.被杀死,回到结点1处(概率为ki) 9 2.找到出口,走出迷宫 (概率为ei) 10 3.和该点相连有m条边,随机走一条 11 求:走出迷宫所要走的边数的期望值. 12 13 设 E[i]表示在结点i处,要走出迷宫所要走的边数的期望.E[1]即为所求. 14 15 叶子结点: 16

hdu 4033 2011成都赛区网络赛 余弦定理+二分 **

二分边长,判断最后内角和是否为2pi,注意l与r的选取,保证能组成三角形 1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #include<queue> 7 #include<map> 8 using namespace std; 9 #define MOD 10000