您的位置:首页 > 理论基础 > 计算机网络

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

2015-07-31 22:00 459 查看
没看过TSP,先mark

//4838039 2011-10-27 23:04:15 Accepted 4026 2343MS 31044K 3143 B C++ Geners
//状态压缩DP的TSP问题
//优先级位运算小于判等 , 还有各种细节各种出错
#include <cstdio>
#include <cstring>
#include <stdlib.h>
#define mabs(a) (a>0?a:-(a))

using namespace std;

typedef long long ll;
const int maxn=1<<17;
int gcd(int a, int b)
{
return b?gcd(b, a%b):a;
}

int g[7][7];
int map[7][7], cnt;
int n, m;
ll dp[maxn][30];
struct Node {
int x,y;
}node[20];

void init ()
{
for (int i=0 ; i<7 ; ++i)
for (int j=0 ; j<7 ; ++j)
g[i][j]=gcd(i, j);
}

bool valid(int sta, int k, int pre)
{
int x=node[k].x,xx=node[pre].x;
int y=node[k].y,yy=node[pre].y;

if(map[x][y]>0 || map[xx][yy]>0)
return false;//如果2个点不都是0。
int d=g[mabs(x-xx)][mabs(y-yy)];
for (int i=1 ; i<=d ; ++i)
{
int tmpx=xx+i*(x-xx)/d;
int tmpy=yy+i*(y-yy)/d;
if(map[tmpx][tmpy] == 1)
return false;//中间点forbidden
if(map[tmpx][tmpy] <= 0)
{
if((sta&(1<<(-map[tmpx][tmpy]))) == 0)
{
return false;
}//中间有未遍历的0。
}
}
return true;
}

void DP()
{
memset (dp, 0, sizeof(dp));
int limit=1<<cnt;
for (int i=0 ; i<limit ; ++i)
{
for (int j=0 ; j<cnt ; ++j)
{
dp[1<<j][j]=1ll;//初始以每个点开始的情况
if(i&(1<<j))
for (int k=0 ; k<cnt ; ++k)
{
if(k==j)continue;
if(i^(1<<j)& (1<<k) )   //k是从此时出发的点,j是要去的点
if(valid(i,j,k))
{
dp[i][j]+=dp[i^(1<<j)][k];
}
}
}
}
ll ans=0ll;
for (int i=0 ; i<cnt ; ++i)
ans+=dp[limit-1][i];
printf("%I64d\n", ans);

}

int main ()
{
init ();
while (~scanf("%d%d", &n, &m))
{
cnt=0;
for (int i=0 ; i<n ; ++i)
{
for (int j=0 ; j<m ; ++j)
{
scanf("%d",&map[i][j]);
if(map[i][j] == 0)
{
node[cnt].x=i;
node[cnt].y=j;
map[i][j]=-cnt;//映射到小于等于0
cnt++;
}
//printf(" %d \n",map[i][j]);
}
}
DP();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: