zoukankan      html  css  js  c++  java
  • HDU 4212(预处理,dfs

    题目:给出1到N的N张纸牌,一共最多有T轮,每轮需要拿出一定总和的牌的组合,问最后最多能拿出多少牌。

    思路:首先应该想到的是预处理出拿出牌的组合,这样每次需要拿出某个数的时候直接从列表里搜索,因为N为22,所以直接dfs枚举。然后就是搜索了,直接写一个dfs搜答案是很容易想到的,但是跑一下会发现即使是样例也很慢。。。实际上这时候只需要稍稍加一点优化就可以过了,我们注意到到达某个状态的时候牌的总和是一定的,反过来,如果已经拿出了某个组合的牌,那么它所在的状态也是确定的。。。拿出牌的方法有2^N种,和预处理的数量是一样的,所以只要加一个vis数组避免状态重复就可以把复杂度限制在2^N。

    #include <iostream>
    #include <map>
    #include <algorithm>
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <vector>
    #include <queue>
    #include <stack>
    #include <functional>
    #include <set>
    #include <cmath>
    #define pb push_back
    #define fs first
    #define se second
    #define sq(x) (x)*(x)
    #define eps 0.0000000001
    #define IINF (1<<30)
    using namespace std;
    typedef long long ll;
    typedef pair<ll,ll> P;
    int T,N;
    int V[30];
    vector<int> tab[39];
    vector<int> tnum[30];
    int vis[1<<22];
    void dfs(int val,int v,int mask,int num){
        if(val>22) return;
        if(v==22){
            if(val<=22){
                tab[val].pb(mask);
                tnum[val].pb(num);
            }
            return;
        }
        dfs(val,v+1,mask,num);
        dfs(val+v+1,v+1,mask+(1<<v),num+1);
    }
    int ans=0;
    void work(int p,int mask,int num){
        if(vis[mask]) return;
        vis[mask]=1;
        ans=max(ans,num);
        if(p==T+1) return;
        for(int i=0;i<tab[V[p]].size();i++){
            int v=tab[V[p]][i];
            if(v>=(1<<N)) continue;
            if(!(mask&v)){
                work(p+1,mask+v,num+tnum[V[p]][i]);
            }
        }
    }
    int cas=0;
    int main(){
        /////freopen("/home/files/CppFiles/in","r",stdin);
        /*    std::ios::sync_with_stdio(false);
            std::cin.tie(0);*/
        dfs(0,0,0,0);
        while(cin>>N>>T){
            memset(vis,0,sizeof vis);
            if(N==0&&T==0) break;
            for(int i=1;i<=T;i++){
                scanf("%d",V+i);
            }
            ans=0;
            work(1,0,0);
            printf("Game %d: %d
    ",++cas,ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    临时表各方式对比
    【译】表变量和临时表的比较(转)
    delete和truncate的一个严重区别
    各种临时表插入数据方式对比(包括自增列和GUID列)
    纤程模式的问题
    转 javascript针对DOM的应用(四)
    转 CSS兼容性(IE和Firefox)技巧大全 (四)
    转 CSS兼容性(IE和Firefox)技巧大全 (五)
    转 javascript针对DOM的应用(三)
    javascript基础知识大全(1)
  • 原文地址:https://www.cnblogs.com/Cw-trip/p/4700409.html
Copyright © 2011-2022 走看看