现在有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;
}