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
  • 相关阅读:
    leetcode 279. Perfect Squares
    leetcode 546. Remove Boxes
    leetcode 312. Burst Balloons
    leetcode 160. Intersection of Two Linked Lists
    leetcode 55. Jump Game
    剑指offer 滑动窗口的最大值
    剑指offer 剪绳子
    剑指offer 字符流中第一个不重复的字符
    leetcode 673. Number of Longest Increasing Subsequence
    leetcode 75. Sort Colors (荷兰三色旗问题)
  • 原文地址:https://www.cnblogs.com/Cw-trip/p/4700409.html
Copyright © 2011-2022 走看看