HIT暑期集训 状压与优化DP
B POJ 2288
题解参考:https://www.cnblogs.com/jackge/archive/2013/05/24/3096162.html
DP还是不会。。
#include<cstdio> #include<cstring> #include<algorithm> #define maxn 15 #define mod 100000000 typedef long long ll; using namespace std; int n,m,mp[maxn][maxn],val[maxn]; int dp[1<<13][maxn][maxn],ans1; ll cnt[1<<13][maxn][maxn],ans2; int main() { int T,i,j,k,x,y,tmp; scanf("%d",&T); while (T--) { memset(mp,0,sizeof(mp)); memset(cnt,0,sizeof(cnt)); memset(dp,-1,sizeof(dp)); scanf("%d%d",&n,&m); for (i=0;i<n;i++) scanf("%d",&val[i]); for (i=1;i<=m;i++) { scanf("%d%d",&x,&y); x--;y--; mp[x][y]=mp[y][x]=1; } if(n==1) { printf("%d 1\n",val[0]); continue; } for (i=0;i<n;i++) for (j=0;j<n;j++) { if (i==j || !mp[i][j]) continue; dp[(1<<i)|(1<<j)][i][j]=val[i]+val[j]+val[i]*val[j]; cnt[(1<<i)|(1<<j)][i][j]=1; } for (i=0;i<(1<<n);i++) for (j=0;j<n;j++) { if (!(i&(1<<j))) continue; for (k=0;k<n;k++) { if (!mp[j][k] || j==k || !(i&(1<<k)) || dp[i][j][k]==-1) continue; for (x=0;x<n;x++) { if (!mp[k][x] || x==j || x==k || (i&(1<<x))) continue; tmp=dp[i][j][k]+val[x]+val[k]*val[x]; if (mp[j][x]) tmp+=val[j]*val[k]*val[x]; if (dp[i|(1<<x)][k][x]<tmp) { dp[i|(1<<x)][k][x]=tmp; cnt[i|(1<<x)][k][x]=cnt[i][j][k]; } else if (dp[i|(1<<x)][k][x]==tmp) cnt[i|(1<<x)][k][x]+=cnt[i][j][k]; } } } ans1=0;ans2=0; for (i=0;i<n;i++) for (j=0;j<n;j++) { if (i==j || !mp[i][j]) continue; if (ans1<dp[(1<<n)-1][i][j]) { ans1=dp[(1<<n)-1][i][j]; ans2=cnt[(1<<n)-1][i][j]; } else if (ans1==dp[(1<<n)-1][i][j]) ans2+=cnt[(1<<n)-1][i][j]; } printf("%d %lld\n",ans1,ans2/2); } return 0; }
E POJ 1821
F POJ 3017
G POJ 3744
H POJ 2373