suoi62 网友跳 (暴搜+dp)

传送门

sbw太神啦orz

首先N<=20可以直接暴搜

然后玄学剪枝可以过18个点

那么N<=40的时候,就把它拆成两半分别暴搜,再用dp拼起来

对于前半段,设f[i][j]是开始高度为i,获得金币为j的方案数;对于后半段,设g[i][j]是结束高度为i,获得金币为j的方案数(离散化一下高度)

然而V<=4e7,并不能直接记

但其实每一段最多只有$2^{20}$种金币数,状压一下每一位选不选,再预处理出来这样的金币数是多少

然后统计答案,$ans=\sum{g[i][j]*f[k][l]},i>k,v[j]+v[l]>=M$

给f做一个前缀和,给每个状态按v排序,可以$O(n*2^{n/2})$统计答案

然后会MLE,注意到对于每种状态其实每个开始高度/结束高度 都只有选或者不选,做个前缀和最多也只有20

把int改成unsigned char 就行了(逃

 1 #include<bits/stdc++.h>
 2 #define pa pair<int,int>
 3 #define CLR(a,x) memset(a,x,sizeof(a))
 4 using namespace std;
 5 typedef long long ll;
 6 const int maxn=45,maxs=(1<<20)+2;
 7 inline ll rd(){
 8     ll x=0;char c=getchar();int neg=1;
 9     while(c<‘0‘||c>‘9‘){if(c==‘-‘) neg=-1;c=getchar();}
10     while(c>=‘0‘&&c<=‘9‘) x=x*10+c-‘0‘,c=getchar();
11     return x*neg;
12 }
13 int H[maxn],N,M,v1[maxs],v2[maxs],rk1[maxs],rk2[maxs];
14 unsigned char f[42][maxs],g[42][maxs];
15 void dfs1(int x,int tar,int h,int y){
16     if(x>tar) return;
17     dfs1(x+1,tar,h,y);
18     if(H[x]>h) f[H[x]][y|(1<<(x-1))]++,dfs1(x+1,tar,H[x],y|(1<<(x-1)));
19 }
20 void dfs2(int x,int tar,int h,int y){
21     if(x<tar) return;
22     dfs2(x-1,tar,h,y);
23     if(H[x]<h) g[H[x]][y|(1<<(x-tar))]++,dfs2(x-1,tar,H[x],y|(1<<(x-tar)));
24 }
25
26 inline bool cmp1(int a,int b){return v1[a]<v1[b];}
27 inline bool cmp2(int a,int b){return v2[a]<v2[b];}
28 int main(){
29     // freopen("62.in","r",stdin);
30     // freopen("62.out","w",stdout);
31     int i,j,k;
32     N=rd(),M=rd();
33     for(i=1;i<=N;i++){
34         rk1[i]=H[i]=rd(),rk2[i]=rd();
35     }
36     sort(rk1+1,rk1+N+1);
37     int t=unique(rk1+1,rk1+N+1)-rk1-1;
38     for(i=1;i<=N;i++)
39         H[i]=lower_bound(rk1+1,rk1+t+1,H[i])-rk1;
40     int m=N>>1;
41     int n1=(1<<m)-1,n2=(1<<(N-m))-1;
42     dfs1(1,m,0,0);
43     dfs2(N,m+1,100,0);
44
45     f[0][0]=1;g[t+1][0]=1;
46     for(i=1;i<=t;i++){
47         for(j=0;j<=n1;j++)
48             f[i][j]+=f[i-1][j];
49     }
50     for(i=1;i<=n1;i++){
51         for(j=1;j<=m;j++)
52             if((i>>(j-1))&1) v1[i]+=rk2[j];
53     }for(i=1;i<=n2;i++){
54         for(j=1;j<=N-m;j++)
55             if((i>>(j-1))&1) v2[i]+=rk2[j+m];
56     }
57     for(i=1;i<=n1;i++) rk1[i]=i;
58     for(i=1;i<=n2;i++) rk2[i]=i;
59     sort(rk1+1,rk1+n1+1,cmp1);
60     sort(rk2+1,rk2+n2+1,cmp2);
61     ll ans=0;
62     for(i=1;i<=t+1;i++){
63         ll s=0;
64         for(j=0,k=n1;j<=n2;j++){
65             for(;k>=0&&v1[rk1[k]]+v2[rk2[j]]>=M;k--)
66                 s+=f[i-1][rk1[k]];
67             ans+=s*g[i][rk2[j]];
68         }
69     }
70     printf("%lld\n",ans);
71     return 0;
72 }

原文地址:https://www.cnblogs.com/Ressed/p/9887324.html

时间: 2024-10-28 10:30:11

suoi62 网友跳 (暴搜+dp)的相关文章

codeforces 339C Xenia and Weights(dp或暴搜)

转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud Xenia and Weights Xenia has a set of weights and pan scales. Each weight has an integer weight from 1 to 10 kilos. Xenia is going to play with scales and weights a little. For this, she puts

子矩阵(暴搜(全排列)+DP)

子矩阵(暴搜(全排列)+DP) 一.题目 子矩阵 时间限制: 1 Sec  内存限制: 128 MB 提交: 1  解决: 1 [提交][状态][讨论版] 题目描述 给出如下定义: 1. 子矩阵:从一个矩阵当中选取某些行和某些列交叉位置所组成的新矩阵(保持行与列的相对顺序)被称为原矩阵的一个子矩阵. 例如,下面左图中选取第2.4行和第2.4.5列交叉位置的元素得到一个2*3的子矩阵如右图所示. 9 3 3 3 9 9 4 8 7 4 1 7 4 6 6 6 8 5 6 9 7 4 5 6 1 的

HDU 4284 Travel Folyd预处理+dfs暴搜

题意:给你一些N个点,M条边,走每条边要花费金钱,然后给出其中必须访问的点,在这些点可以打工,但是需要先拿到证书,只可以打一次,也可以选择不打工之直接经过它.一个人从1号点出发,给出初始金钱,问你能不能访问所以的点,并且获得所以证书. 题解:目标是那些一定要访问的点,怎么到达的我们不关心,但是我们关系花费最少的路径,而且到达那个点后是一定要打工的,如果只是经过,那么在求花费最少的路径的时候已经考虑过了. 因此先用Folyd求出各个点直接的最短路径,由于N很小,又只要求出一个解,所以直接dfs暴搜

codeforces339C - Xenia and Weights 暴搜

题意:给你无穷多个1-10的,从 1-m不停的放到天平两端,两次连续放置要在不同的天平和放不同的重量,使得每一次放置这边的天平都比对面的重量多. 解题思路: 1)暴搜,如果估算的话还是过不了的,但实际情况比估算好太多了   62ms 1 // File Name: 339c.cpp 2 // Author: darkdream 3 // Created Time: 2014年08月03日 星期日 16时38分23秒 4 5 #include<vector> 6 #include<list

Hdu 4016 Magic Bitwise And Operation (暴搜 dfs)

题目大意: 在n个数中选取k个数,是他们的按位与最小. 思路分析: 开始往dp想,但是这道题是不满足子问题的. 当前的值最小,但是丢掉了和后面的1错开的最多的状态. 暴搜的剪枝: 1.与后面所有的树相与都比ans小,剪掉,因为越与越小. 2.先将所有的数排序,先取小的. 3.ans可以不断更新,不需要达到k的时候更新,原因和1相同. #include <cstdio> #include <iostream> #include <cstring> #include <

【BZOJ-3033】太鼓达人 欧拉图 + 暴搜

3033: 太鼓达人 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 204  Solved: 154[Submit][Status][Discuss] Description 七夕祭上,Vani牵着cl的手,在明亮的灯光和欢乐的气氛中愉快地穿行.这时,在前面忽然出现了一台太鼓达人机台,而在机台前坐着的是刚刚被精英队伍成员XLk.Poet_shy和lydrainbowcat拯救出来的的applepi.看到两人对太鼓达人产生了兴趣,applepi果断闪

c++20701除法(刘汝佳1、2册第七章,暴搜解决)

20701除法 难度级别: B: 编程语言:不限:运行时间限制:1000ms: 运行空间限制:51200KB: 代码长度限制:2000000B 试题描述     输入正整数n,按从小到大的顺序输出所有满足表达式abcde/fghij=n的abcde和fghij,其中a~j恰好为数字0~9的一个排列. 如果没有符合题意的数,输出0.本题所说的五位数可以包括前导0的,如01234在这里也称为五位数. 输入 一个正整数n  输出 若干行,每行包括两个符合要求的五位正整数(每行的两个数先大后小),两数之

[HDU 5135] Little Zu Chongzhi&#39;s Triangles (dfs暴搜)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5135 题目大意:给你n条边,选出若干条边,组成若干个三角形,使得面积和最大.输出最大的面积和. 先将边从小到大排序,这样前面的两条边加起来如果不大于第三条边就可以跳出,这是一个存在性条件. dfs(int idx,int now,int cnt,int nowmax)代表我当前处理的是第idx条边,已经加入边集的有cnt条边,当前的边的长度和为now,组成的最大面积和为nowmax. 暴力枚举每个三

HDU 5012 bfs暴搜

Dice Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 243    Accepted Submission(s): 135 Problem Description There are 2 special dices on the table. On each face of the dice, a distinct number wa