现在有n个人排成一队(2<=n<=18)
给你一个n*n的矩阵
Wij代表 i在j的前面的话 i给j带来多大的舒适度
如果i排在最前面 前面没有人的话 则带来Wii的舒适度
所以现在要你问你 怎么排 可以排出 最大舒适度的队伍 求最大舒适度是多少
题解:
由于n并不大 那么我们可以用一个0 ---- (1<<18 - 1)的范围表示当前有哪些队伍已经排好了
即状压DP思想
我们可以开一个 dp[1<<18][19] 表示dp[当前的状态][当前状态的最后一位为多少] 所得到的舒适度
AC_code:
#include <iostream>
#include <algorithm>
using namespace std;
int dp[1<<18][20];
int w[20][20];
int main() {
int n;
cin>>n;
for(int i=0; i<n; ++i) {
for(int j=0; j<n; ++j) {
cin>>w[i][j];
}
}
// 为0表示没进去队列 为1表示已经进去了队列
for(int i=0; i<(1<<n); ++i) {
for(int j=0; j<n; ++j) {
if((i&(1<<j))==0) {//i 第j位为0
if(i==0) dp[i|(1<<j)][j]=max(dp[i|(1<<j)][j],w[j][j]); // i为0 i|(1<<j)把i的第j位化为1
else {// i不为为0 i|(1<<j)把i的第j位化为1
for(int k=0; k<n; ++k) {
if((i&(1<<k))==0) continue; // i的第k位为 0
dp[i|(1<<j)][j]=max(dp[i|(1<<j)][j],dp[i][k]+w[j][k]);
}
}
}
}
}
int ans=-1;
for(int i=0; i<n; ++i) {
ans=max(dp[(1<<n)-1][i], ans);
}
cout<<ans<<endl;
return 0;
}