dp[i][j][k]代表到第i个位置,第i个位置是j,k为已经选了i个数分别是那些(2进制状压)
然后:其实真正有用的状态很少,可以写记忆化搜索,我写的BFS加速
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <string> #include <stack> #include <vector> #include <map> #include <queue> #include <algorithm> #include <utility> using namespace std; typedef long long LL; const int N=15; const int INF=-15*(1e8+5); const LL mod=1e9+7; int dp[17][17][65537]; bool inq[17][17][65537]; int a[20],p[20],n; int vis[20]; struct Node{ int pos,u,cur; // Node(int a,int b,int c){pos=a;u=b;cur=c;} }; queue<Node>q; int main() { int T,cas=0; scanf("%d",&T); while(T--){ printf("Case #%d:\n",++cas); memset(vis,0,sizeof(vis)); scanf("%d",&n); for(int i=1;i<=n;++i){ scanf("%d%d",&a[i],&p[i]); if(p[i]!=-1){ ++p[i]; vis[p[i]]=i; } } int l=(1<<n)-1; for(int i=0;i<=n;++i) for(int j=0;j<=n;++j) for(int k=0;k<=l;++k) dp[i][j][k]=INF; memset(inq,0,sizeof(inq)); q.push(Node{0,0,0});dp[0][0][0]=0; while(!q.empty()){ Node e=q.front(); q.pop(); int pos=e.pos+1; if(vis[pos]&&(e.cur&(1<<(vis[pos]-1)))==0){ int aim=e.cur|(1<<(vis[pos]-1)); if(dp[pos][vis[pos]][aim]==INF)q.push(Node{pos,vis[pos],aim}); dp[pos][vis[pos]][aim]=max(dp[pos][vis[pos]][aim],dp[e.pos][e.u][e.cur]+a[e.u]*a[vis[pos]]); continue; } for(int i=1;i<=n;++i){ if(p[i]!=-1)continue; if(e.cur&(1<<(i-1)))continue; int aim=e.cur|(1<<(i-1)); if(dp[pos][i][aim]==INF)q.push(Node{pos,i,aim}); dp[pos][i][aim]=max(dp[pos][i][aim],dp[e.pos][e.u][e.cur]+a[e.u]*a[i]); } } int ans=INF; for(int i=1;i<=n;++i) ans=max(ans,dp[n][i][l]); printf("%d\n",ans); } return 0; }
时间: 2024-10-05 12:59:01