题意:
给定n个物品,每个物品都有一个满意度v,现在从n个物品中选取m个,选的过程中有几个规则,它们是基于选择顺序给出的规则,例如:选择的过程中a和b相邻,且a在b的前面,则满意度增加c,现在给出了k个这样的规则。问你根据这些规则,从n个物品中选取m个的最大满意度是多少。
范围:
0<=n,m<=18,k<=n*(n-1),v<=10^9
分析:
通过n和m的范围,很容易想到对状态进行压缩。
我的初始错误解法:dp[mask]表示当前的状态,然后遍历n个物品,若i不再mask中,则加入;并且遍历与i有关的规则,若i,j都不在,在加入i,j。
上述状态表示不知道当前结尾的物品是什么,反应的信息不够,最终任何两个相邻的物品,都要根据规则来进行加分,但是上述状态是没法做到这样的。
所以改变状态表示dp[mask][i]表示当前物品状态为mask,且结尾的物品为i,这样就可以根据物品i和规则来进行转移了。
注意:因为满意度可以为0,所以初始化dp[][]的时候,要初始化为-1,初始化为0是错的。
具体代码:
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define N 300010
typedef long long LL;
#define aa frist
#define bb second
int n,m,k;
LL a[20],dp[N][19];
//vector > rule[20];
int cal(int v)
{
int num=0;
while(v>0)
{
if(v&1) num++;
v/=2;
}
return num;
}
LL rs[20][20];
int main()
{
while(scanf("%d%d%d",&n,&m,&k)!=EOF) //
{
for(int i=0; i