题目:一些朋友旅游,他们的路线及起点终点都已经确定。每个人都可以中途离开队伍,或者干脆就不去,
一旦离开就不可以再回来;每座城市都有一个消费值cost;每个人对每座城市有一个兴趣值inter;
只要两个人呆在一起,他们就可以获得一个共享福利bonus;现在要求可能获得的总最大值;
若总最大值为负,则输出 STAY HOME。
分析:dp,状态压缩。
阶段:以景点的参观顺序为阶段;
状态:参观到每个景点时 N 个人会有2^N 种状态(每个人去不去);
决策:当前景点如果 某个人在参观则前面的景点必然参观,否则有两种可能(上个景点参观否);
取得其中的最大值 + 这个景点本状态能获得的价值;
处理:2^10 = 1024 用位运算处理方便一些,决策过程中可利用heap或者bfs求出所有的之前状态。
说明:(2011-09-18 23:59)。
#include <iostream>
#include <cstdlib>
#include <cstring>
using namespace std;
int Maps[ 11 ][ 11 ];
int Cost[ 11 ];
int Inst[ 11 ][ 11 ];
int F[ 11 ][ 1025 ];
int Stat[ 11 ];
int Q[ 11 ][ 1025 ];
int main()
{
int N,M;
while ( cin >> N >> M && N ) {
for ( int i = 1 ; i <= M ; ++ i )
cin >> Cost[ i ];
for ( int i = 1 ; i <= N ; ++ i )
for ( int j = 1 ; j <= M ; ++ j )
cin >> Inst[ i ][ j ];
for ( int i = 1 ; i <= N ; ++ i )
for ( int j = 1 ; j <= N ; ++ j )
cin >> Maps[ i ][ j ];
int V = (1<<N)-1;
for ( int i = 0 ; i <= N ; ++ i )
for ( int j = 0 ; j <= V ; ++ j )
F[ i ][ j ] = -10000001;
for ( int j = 0 ; j <= V ; ++ j )
F[ 0 ][ j ] = 0;
for ( int i = 1 ; i <= M ; ++ i )
for ( int j = 0 ; j <= V ; ++ j ) {
//将位状态存入数组
int temp = j;
for ( int k = 1 ; k <= N ; ++ k ) {
Stat[ k ] = temp%2;
temp /= 2;
}
//求出这个状态能得到的价值
int Save = 0;
for ( int k = 1 ; k <= N ; ++ k )
if ( Stat[ k ] )
Save += Inst[ k ][ i ] - Cost[ i ];
for ( int p = 1 ; p <= N ; ++ p )
for ( int q = p+1 ; q <= N ; ++ q )
if ( Stat[ p ] && Stat[ q ] )
Save += Maps[ p ][ q ];
//求出所有的之前状态
int count = 0;
Q[ 0 ][ 0 ] = j;
for ( int k = 1 ; k <= N ; ++ k )
if ( !Stat[ k ] ) {
for ( int p = 0 ; p < (1<<count) ; ++ p ) {
int New = Q[ count ][ p ];
Q[ count+1 ][ p*2+0 ] = New;
Q[ count+1 ][ p*2+1 ] = New|(1<<(k-1));
}
++ count;
}
//取得之前状态的最大值
int Min = -10000001;
for ( int k = 0 ; k < (1<<count) ; ++ k ) {
// cout << Q[ count ][ k ] << " ";
if ( Min < F[ i-1 ][ Q[ count ][ k ] ] )
Min = F[ i-1 ][ Q[ count ][ k ] ];
}
F[ i ][ j ] = Min+Save;
// cout << "V = " << F[ i ][ j ] << endl;
}
int Max = -10000001;
for ( int i = 1 ; i <= M ; ++ i )
for ( int j = 0 ; j <= V ; ++ j )
if ( Max < F[ i ][ j ] )
Max = F[ i ][ j ];
if ( Max > 0 )
cout << Max << endl;
else
cout << "STAY HOME" << endl;
}
return 0;
}