hdu 5691 Sitting in Line 状压dp
2016-05-24 21:53
302 查看
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=5691题解:
和tsp用的状压差不多,就是固定了一些访问顺序。dp[i][j]表示前cnt个点中布满状态i且最后一个为j的状态的最大乘积和。
则有dp[i|(1<<k)][k]=max(dp[i|(1<<k)][k],dp[i][j]+a[j]*a[k])。
#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> using namespace std; const int maxn = 22; const int INF = 2e9; int dp[1 << 16][22]; int cnt[1 << 16]; int a[maxn], p[maxn],f[maxn]; int n; void pre() { for (int i = 0; i < (1 << 16); i++) { cnt[i] = 0; for (int j = 0; j < 16; j++) { if (i&(1 << j)) cnt[i]++; } } } void init() { for (int i = 0; i < (1 << n); i++) { for (int j = 0; j <= n; j++) { dp[i][j] = -INF; } } memset(f, -1, sizeof(f)); } int main() { pre(); int tc,kase=0; scanf("%d", &tc); while (tc--) { scanf("%d", &n); init(); for (int i = 0; i < n; i++) { scanf("%d%d", a + i, p + i); if (p[i] != -1) f[p[i]] = i; } a = 0; p = n; dp[0] = 0; for (int i = 0; i < (1 << n); i++) { int sum = cnt[i]; for (int j = 0; j <= n; j++) { if ((i&(1 << j)) == 0&&j!=n) continue; //被限制的点: if (f[sum] != -1) { if ((i&(1 << f[sum])) == 0) { dp[i | (1 << f[sum])][f[sum]] = max(dp[i | (1 << f[sum])][f[sum]], dp[i][j]+a[j]*a[f[sum]]); } } else { //可以自由移动的点 for (int k = 0; k < n; k++) { if (i&(1 << k)) continue; if (p[k] ==-1) { dp[i | (1 << k)][k] = max(dp[i | (1 << k)][k], dp[i][j] + a[j] * a[k]); } } } } } int ans = -INF; for (int j = 0; j < n; j++) ans = max(ans, dp[(1 << n) - 1][j]); printf("Case #%d:\n", ++kase); printf("%d\n", ans); } return 0; }
再一发:
#include<map> #include<set> #include<cmath> #include<queue> #include<stack> #include<ctime> #include<vector> #include<cstdio> #include<string> #include<bitset> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> #include<functional> using namespace std; #define X first #define Y second #define mkp make_pair #define lson (o<<1) #define rson ((o<<1)|1) #define mid (l+(r-l)/2) #define sz() size() #define pb(v) push_back(v) #define all(o) (o).begin(),(o).end() #define clr(a,v) memset(a,v,sizeof(a)) #define bug(a) cout<<#a<<" = "<<a<<endl #define rep(i,a,b) for(int i=a;i<(b);i++) #define scf scanf #define prf printf typedef long long LL; typedef vector<int> VI; typedef pair<int,int> PII; typedef vector<pair<int,int> > VPII; const int INF=0x3f3f3f3f; const LL INFL=10000000000000000LL; const double eps=1e-9; const double PI = acos(-1.0); //start---------------------------------------------------------------------- const int maxn=17; LL dp[1<<maxn][maxn]; LL arr[maxn]; int pos[maxn],mp[maxn]; int sumv[1<<maxn]; int n; void pre(){ clr(sumv,0); for(int i=0;i<(1<<maxn);i++){ for(int j=0;j<maxn;j++){ if(i&(1<<j)){ sumv[i]++; } } } } void init(){ clr(mp,-1); } int main() { pre(); int tc,kase=0; scf("%d",&tc); while(tc--){ scf("%d",&n); init(); rep(i,0,n){ scf("%lld%d",&arr[i],&pos[i]); if(pos[i]>=0) mp[pos[i]]=i; } rep(i,0,(1<<maxn)) rep(j,0,maxn) dp[i][j]=-INFL; if(mp[0]>=0){ dp[1<<mp[0]][mp[0]]=0; }else{ for(int i=0;i<n;i++){ if(pos[i]>=0) continue; dp[1<<i][i]=0; } } rep(i,1,(1<<n)){ rep(j,0,n){ if(!(i&(1<<j))) continue; if(mp[sumv[i]-1]>=0&&mp[sumv[i]-1]!=j) continue; rep(k,0,n){ if(k==j||!(i&(1<<k))) continue; if(mp[sumv[i^(1<<j)]-1]>=0&&mp[sumv[i^(1<<j)]-1]!=k) continue; dp[i][j]=max(dp[i][j],dp[i^(1<<j)][k]+arr[k]*arr[j]); } } } LL ans=-INFL; rep(i,0,n) ans=max(ans,dp[(1<<n)-1][i]); prf("Case #%d:\n",++kase); prf("%lld\n",ans); } return 0; } //end-----------------------------------------------------------------------
相关文章推荐
- 看鸟哥写的计算机概论收获
- Nutch2.2.3源码阅读之injectorJob
- 分治算法介绍
- 开启博客之旅
- MySql知识
- c++第六次作业
- 零碎知识之:<map><area>
- 2016"百度之星" - 初赛(Astar Round2A) 1002
- (4)表达式
- python 2.7中安装mysql
- Linux操作系统基础解析之(六)——文件系统层次结构标准(FHS)
- python 2.7中安装mysql
- 第一篇博客
- (4.6.12.2)uses-permission权限列表
- python 2.7中安装mysql
- AlertDialog.Builder的setCancelable
- js阻止事件的传播
- 根据“+”号,获取数字图片,数值变大变小,温度上升,降低
- Python之时间处理模块time
- Struts2_CRUD操作实例