zoukankan      html  css  js  c++  java
  • CF580D Kefa and Dishes(经典状压)

    分析:
    本题是一道状压dp的经典题目,我相信很多人都做过最短哈密顿路径,只要做过那道题,这道题就迎刃而解。
    我们自然想到可以用f[i][j]表示当前已经吃过i,这次吃的是j来表示状态,注意i是用二进制表示的,每个食物都对应一个位置
    因此我们就能用除去j且包含k的集合来更新这个状态。
    因为题目说如果k在j前面一个吃并且满足题目的rule,就额外加值,我们可以在预处理的时候先算,我采用了map存储,当然也可用二维数组。
    因为我们转移的时候一定是刚吃k然后吃j的。
    本题爆int并注意只能吃m个

    #include<algorithm>
    #include<iostream>
    #include<cstdio>
    #include<vector>
    #include<cstring>
    #include<string> 
    #include<set>
    #include<map>
    #include<queue>
    using namespace std;
    typedef long long ll;
    typedef pair<int,int> pll;
    const int N=20;
    const int inf=0x3f3f3f3f;
    ll f[1<<N][N];
    int i;
    int n,m,k;
    int a[N];
    int x,y;
    int w;
    map<pll,int> m1;
    bool check(int x){
        int res=0;
        for(i=0;i<n;i++){
            if(x>>i&1)
            res++;
        }
        if(res==m)
        return  true;
        else
        return false;
    }
    int main(){
           cin>>n>>m>>k;
           int i,j;
           for(i=0;i<n;i++){
               cin>>a[i];
        }
        for(i=1;i<=k;i++){
            cin>>x>>y>>w;
            x--;
            y--;
            m1[pll(x,y)]=w;    
        }
        memset(f,-0x3f,sizeof f);
        f[0][0]=0;
        for(i=0;i<1<<n;i++){
            for(j=0;j<n;j++){
                if(i>>j&1){
                    f[i][j]=a[j];
                 for(k=0;k<n;k++){
                    if(k==j)
                    continue;
                    if(i>>k&1){
                        if(m1[pll(k,j)]){
                            f[i][j]=max(f[i][j],f[i-(1<<j)][k]+a[j]+m1[pll(k,j)]);
                        }
                        else
                            f[i][j]=max(f[i][j],f[i-(1<<j)][k]+a[j]);
                    }
                }    
                }
                
            }
        }
        ll res=0;
        for(i=0;i<1<<n;i++){
            if(check(i)){
                for(j=0;j<n;j++){
                    res=max(res,f[i][j]);
                }
            }
        }
        cout<<res<<endl;
        return 0;
    }
    View Code
  • 相关阅读:
    Luogu P4246 [SHOI2008]堵塞的交通(线段树+模拟)
    Luogu P2619 [国家集训队2]Tree I(WQS二分+最小生成树)
    Luogu P2042 [NOI2005]维护数列(平衡树)
    Luogu P1052 过河(dp)
    Luogu P1041 传染病控制(搜索)
    Luogu P2717 寒假作业(平衡树)
    Luogu P2822 组合数问题(前缀和)
    Luogu P2827 蚯蚓(模拟)
    随机图片测试
    Luogu P2458 [SDOI2006]保安站岗(树形dp)
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/12386693.html
Copyright © 2011-2022 走看看