• hdu 5691 Sitting in Line 状压dp


    题目链接:

    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[n] = 0; p[n] = n;
            dp[0][n] = 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:
    ", ++kase);
            printf("%d
    ", 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:
    ",++kase);
            prf("%lld
    ",ans);
    
        }
        return 0;
    }
    
    //end-----------------------------------------------------------------------
  • 相关阅读:
    冲刺周2
    java 流
    java 线程控制方法
    java界面编程(下)
    java 界面编程(上)
    java数组
    java 异常
    java程序中的存储区
    java中稍微有些陌生的关键字
    IOCP服务器搭建
  • 原文地址:https://www.cnblogs.com/fenice/p/5525001.html
Copyright © 2020-2023  润新知