这是一道状态压缩DP题目
用dp[i][1024] 可以记下经过第i个城市的所有状态
在状态转移的时候,dp[i-1][j]中的j必须在 dp[i][k] 的k为1的对应位上也为1
例如,如果k为10110,那么j可以使10110或10111或11110或11111或10110,我们可以提前处理出所有能转移到k的状态
转移过程就非常简单了
做这道题的时候再位运算的处理上wrong answer 了好几次,最后竟然是错在位运算运算符的优先级上~~
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <memory.h>
#include <vector>
using namespace std;
const int N = 1025;
const int M = 15;
const int INF = 1 << 30;
int g_cost[M];
int g_n,g_m;
struct fiend
{
int interest[M];
int value[M];
void getvalue()
{
for(int i = 1;i <= g_m;i++)
value[i] = interest[i] - g_cost[i];
}
}g_f[M];
vector<int> g_havepeo[N],g_before[N];
int g_relation[M][M];
int dp[M][N];
int g_len,g_ship[N];
void INIT();
void sol();
int getfriendship(int i);
int increase(int j,int gap);
int main()
{
INIT();
while(scanf("%d%d",&g_n,&g_m)!=EOF &&(g_n || g_m))
{
for(int i = 1;i <= g_m;i++)
scanf("%d",&g_cost[i]);
for(int i = 1;i <= g_n;i++)
{
for(int j = 1;j <= g_m;j++)
scanf("%d",&g_f[i].interest[j]);
}
for(int i = 1;i <= g_n;i++)
for(int j = 1;j <= g_n;j++)
scanf("%d",&g_relation[i][j]);
for(int i = 1;i <= g_n;i++)g_f[i].getvalue();
g_len = 1 << g_n;
sol();
}
}
void INIT()
{
int x[11];
x[1] = 1;
for(int i = 2;i < 11;i++)x[i] = x[i-1] << 1;
for(int i = 0;i < 1024;i++)
{
g_havepeo[i].clear();
for(int j = 1;j < 11;j++)
if(i & x[j])
g_havepeo[i].push_back(j);
}
for(int i = 0;i < 1024;i++)
{
g_before[i].clear();
for(int j = i;j < 1024;j++)
{
if((j&i) == i)
{
g_before[i].push_back(j);
}
}
}
memset(dp,0,sizeof(dp));
}
void sol()
{
for(int i = 1;i < g_len;i++)
{
g_ship[i] = getfriendship(i);
}
for(int gap = 1;gap <= g_m;gap++)
{
for(int j = 0;j < g_len;j++)
{
int tmp = increase(j,gap) + g_ship[j];
int max = -INF;
for(int k = 0;k < g_before[j].size()&&g_before[j][k] < g_len;k++)
{
if(tmp + dp[gap-1][g_before[j][k]] > max)
max = tmp + dp[gap-1][g_before[j][k]];
}
dp[gap][j] = max;
}
}
int max = -INF;
for(int i = 0;i <= g_len;i++)
{
if(dp[g_m][i] > max)
max = dp[g_m][i];
}
if(max <= 0) printf("STAY HOME\n");
else if(max > 0) printf("%d\n",max);
}
int getfriendship(int i)
{
int tmp = 0;
for(int j = 0;j < g_havepeo[i].size();j++)
{
for(int k = j;k < g_havepeo[i].size();k++)
{
tmp += g_relation[g_havepeo[i][j]][g_havepeo[i][k]];
}
}
return tmp;
}
int increase(int j,int gap)
{
int tmp = 0;
for(int i = 0;i < g_havepeo[j].size();i++)
{
tmp += g_f[g_havepeo[j][i]].value[gap];
}
return tmp;
}