1. 程式人生 > 實用技巧 >HIT暑期集訓 狀壓與優化DP

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; }
View Code

E POJ 1821

F POJ 3017

G POJ 3744

H POJ 2373