第一个问题:
先枚举出所有可能的组合,然后剩下的就是01背包了。。。。
第二个问题:多旅行商问题
可以先求单个的旅行商,然后再合成多个的
说实话第一次见到旅行商问题。。。。还是个多旅行商问题。。。。
np[i]表示 经过i这个状态中的点后回到0点的最小时间
cost[j][i]表示经过i中的状态的点后最后经过的是点j
然后求出单个的之后,从0开始dp上去,每次求得都是i状态下的最小时间
AC代码如下:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
#define MAX 0x3f3f3f3f
typedef struct{
double x, y;
}Point;
int N, M;
Point p[20];
int weight[20];
int dp[1<<16];
int dis[20][20];
int cost[16][1<<16];
int np[1<<16];
bool oki[1<<16];
int maxweight;
int statu[1<<16], tot;
bool ok( int s ){
int sum = 0;
for( int i = 0; i < N; i++ ){
if( s & ( 1 << i ) ){
sum += weight[i];
}
}
if( sum <= M ){
return true;
}else{
return false;
}
}
void initial(){
memset( dis, 0, sizeof( dis ) );
for( int i = 0; i < N; i++ ){
for( int j = i + 1; j < N; j++ ){
double a = p[i].x - p[j].x;
double b = p[j].y - p[i].y;
dis[i][j] = dis[j][i] = ceil( sqrt( a * a + b * b ));
}
}
tot = 0;
for( int i = 0; i < ( 1 << N ); i++ ){
oki[i] = ok(i);
if( oki[i] ){
statu[tot++] = i;
}
}
}
int solve_first(){
memset( dp, 0x3f, sizeof( dp ) );
dp[0] = 0;
for( int i = 1; i < ( 1 << N ); i++ ){
for( int j = 0; j < tot; j++ ){
if( ( i | statu[j] ) == i ){
dp[i] = min( dp[i], dp[i-statu[j]] + 1 );
}
}
}
return dp[(1<<N)-1] == MAX ? -1 : dp[(1<<N)-1];
}
int solve_second(){
memset( np, 0x3f, sizeof( np ) );
memset( cost, 0x3f, sizeof( cost ) );
cost[0][1] = 0;
for( int i = 1; i < ( 1 << N ); i++ ){
if( !oki[i] ){
continue;
}
for( int j = 0; j < N; j++ ){
if( i & ( 1 << j ) ){
np[i] = min( np[i], cost[j][i] + dis[j][0] );
for( int k = 0; k < N; k++ ){
if( ( i & ( 1 << k ) ) == 0 ){
cost[k][i|(1<<k)] = min( cost[k][i|(1<<k)], cost[j][i] + dis[j][k] );
}
}
}
}
}
for( int i = 1; i < ( 1 << N ); i++ ){
for( int j = ( ( i - 1 ) & i ); j; j = ( ( j - 1 ) & i ) ){
np[i] = min( np[i], np[j|1] + np[(i-j)|1] );
}
}
return np[(1<<N)-1];
}
int main(){
while( scanf( "%d%d", &N, &M ) != EOF ){
for( int i = 0; i < N; i++ ){
scanf( "%lf%lf", &p[i].x, &p[i].y );
}
for( int i = 0; i < N; i++ ){
scanf( "%d", &weight[i] );
maxweight = max( weight[i], maxweight );
}
initial();
int ans1 = solve_first();
if( ans1 == -1 ){
cout << -1 << " " << -1 << endl;
continue;
}
cout << ans1 << " " << solve_second() << endl;
}
return 0;
}