http://acm.hdu.edu.cn/showproblem.php?pid=5691 题目;
题意是给你一堆数。。有的有限制在第几个有的不限制在第几个。。问如何排列相邻的乘积相加最后最大。。
坑爹初始化错了wa了好长时间。。放下一段时间回来看发现初始化错了。。
这里考虑状压dp,dp[ i ] [ j ] 表示 i 状态下 最后一个乘的是 j 的时候的最大值。。。
还是记忆化搜索好写一些,也不是很慢。代码如下。。。太弱了,以后加油- -。。
#include <cstdio>
#include <queue>
#include <cmath>
#include <cstring>
#include <iostream>
using namespace std;
int n;
long long dp[1<<16][16],vis[1<<16][16],arr[16],index[16];
long long inf=-1e9;
long long DP(int st,int p,int cnt){
if(vis[st][p]!=0)
return dp[st][p];
if(index[cnt]!=-1&&index[cnt]!=p){
vis[st][p]=1;
dp[st][p]=inf;
return inf;
}
if(cnt==0){
vis[st][p]=1;
dp[st][p]=0;
return 0;
}
dp[st][p]=inf;
int nst=(st^(1<<p));
for(int i=0;i<n;i++){
if((nst>>i)&1)
dp[st][p]=max(dp[st][p],DP(nst,i,cnt-1)+arr[i]*arr[p]);
}
vis[st][p]=1;
return dp[st][p];
}
int main(){
int t,cas=0;
scanf("%d",&t);
while(t--){
memset(dp,0,sizeof(dp));
memset(vis,0,sizeof(vis));
memset(index,-1,sizeof(index));
int a,b;
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d%d",&a,&b);
if(b!=-1)
index[b]=i;
arr[i]=a;
}
int mx=(1<<n)-1;
long long ret=inf;
for(int i=0;i<n;i++) ret=max(DP(mx,i,n-1),ret);
cout<<"Case #"<<++cas<<":
"<<ret<<endl;
}
}
/******
16
-10000 0
-10000 -1
-10000 2
-10000 -1
-10000 4
10000 5
10000 -1
10000 7
10000 -1
-10000 8
-10000 -1
-10000 9
10000 -1
10000 10
10000 -1
10000 -1
******/