[折半搜索 剪枝 随机化染色] 2015 计蒜之道 复赛 腾讯的星钻增值服务
2016-11-12 11:12
351 查看
题解里说的很详细 实在没有想到0.94的出错率 都可以随机化 不过在数据范围小 可以进行较多次随机的情况下 每次都出错的几率就很小了
http://blog.jisuanke.com/?p=146
先让我们来思考一下,如果这个问题被简化成“七种不同的星数分别为1, 2, 3, … 7”,这个问题应该如何解?
由于背包的最大负重和代价都比较大,所以直接做 0/1 背包难度稍大。但是由于总的星钻个数比较少,因此我们可以使用折半的方法,分别枚举四种、其余三种星钻怎么选取,得到所有可能的方案,再考虑合并(这里需要排序)。
一种简单的考虑是,假设每个星钻的星数是在 1~7 种 uniformly random 的,那么每种星数的星钻大致会在15(≈ 100/7)个左右,所以枚举的量会在154 ≈ 5 × 104。
更一般的来看,考虑每种星钻的个数已知的情况下,我们可以通过枚举如何按照星数的不同分 2 组(共27 − 2种不同的分组方案),使得分出的 2 组内部组合数的最大值最小。所以,无论 7 种星钻的个数怎么分布,最坏情况下我们需要枚举的量在1.3 × 105以内。证明如下:
假设在最优分组的情况下,较小的组合数为
prod???,较大的组合数为 prodmax。由此,prod??? ×N ≥
prodmax。 又因为 prod??? × prodmax 为所有数的总乘积,这些数的总和为 ?,所以总乘积最大为 (N/7)7。所以
![](http://blog.jisuanke.com/wp-content/uploads/2015/08/q9.png)
基于 random simulation 最坏为 154,应该可以找到理论证,但这里有这个很松的界就足够了。
接下来,我们来看看星数很多的情况。核心的思想是随机染色。
首先将不同的星数随机映射到 1 到 7。假设正确答案只对应一种方案,那么在一次随机染色种,这个最佳方案中的 7 种星数被映射到 7 种不同的颜色的概率为
![](http://blog.jisuanke.com/wp-content/uploads/2015/08/q10.png)
在随机染色之后,就可以用上文提到的简单版本的方法来解决。
假设我们反复执行随机染色 1000 次,那么每一次都错误的概率为(1 − 0.006)1000 ≈ 0.002,已经是一个可以接受的范围了。如果没有通过,可以修改随机的种子后再次提交。
http://blog.jisuanke.com/?p=146
先让我们来思考一下,如果这个问题被简化成“七种不同的星数分别为1, 2, 3, … 7”,这个问题应该如何解?
由于背包的最大负重和代价都比较大,所以直接做 0/1 背包难度稍大。但是由于总的星钻个数比较少,因此我们可以使用折半的方法,分别枚举四种、其余三种星钻怎么选取,得到所有可能的方案,再考虑合并(这里需要排序)。
一种简单的考虑是,假设每个星钻的星数是在 1~7 种 uniformly random 的,那么每种星数的星钻大致会在15(≈ 100/7)个左右,所以枚举的量会在154 ≈ 5 × 104。
更一般的来看,考虑每种星钻的个数已知的情况下,我们可以通过枚举如何按照星数的不同分 2 组(共27 − 2种不同的分组方案),使得分出的 2 组内部组合数的最大值最小。所以,无论 7 种星钻的个数怎么分布,最坏情况下我们需要枚举的量在1.3 × 105以内。证明如下:
假设在最优分组的情况下,较小的组合数为
prod???,较大的组合数为 prodmax。由此,prod??? ×N ≥
prodmax。 又因为 prod??? × prodmax 为所有数的总乘积,这些数的总和为 ?,所以总乘积最大为 (N/7)7。所以
![](http://blog.jisuanke.com/wp-content/uploads/2015/08/q9.png)
基于 random simulation 最坏为 154,应该可以找到理论证,但这里有这个很松的界就足够了。
接下来,我们来看看星数很多的情况。核心的思想是随机染色。
首先将不同的星数随机映射到 1 到 7。假设正确答案只对应一种方案,那么在一次随机染色种,这个最佳方案中的 7 种星数被映射到 7 种不同的颜色的概率为
![](http://blog.jisuanke.com/wp-content/uploads/2015/08/q10.png)
在随机染色之后,就可以用上文提到的简单版本的方法来解决。
假设我们反复执行随机染色 1000 次,那么每一次都错误的概率为(1 − 0.006)1000 ≈ 0.002,已经是一个可以接受的范围了。如果没有通过,可以修改随机的种子后再次提交。
#include<cstdio> #include<cstdlib> #include<algorithm> using namespace std; typedef long long ll; inline char nc(){ static char buf[100000],*p1=buf,*p2=buf; if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; } return *p1++; } inline void read(int &x){ char c=nc(),b=1; for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1; for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b; } const int N=105; int n,m; int S ,W ,C ,Clr ; int cot[7],lst[7] ; int clr[7]; struct abcd{ ll p,t; abcd(ll p=0,ll t=0):p(p),t(t) { } bool operator < (const abcd &B) const{ return p<B.p; } }rec[150005]; int tot=0; inline void dfs1(int cur,ll p,ll t){ if (p>m) return; if (cur==7){ rec[++tot]=abcd(p,t); return; } if (clr[cur]){ for (int i=1;i<=cot[cur];i++) dfs1(cur+1,p+W[lst[cur][i]],t+C[lst[cur][i]]); }else dfs1(cur+1,p,t); } ll ret,Ans; inline void dfs2(int cur,ll p,ll t){ if (p>m) return; if (t>Ans) return; if (cur==7){ int iter=upper_bound(rec+1,rec+tot+1,abcd(m-p,1LL<<60))-rec-1; if (iter) ret=min(ret,t+rec[iter].t); return; } if (!clr[cur]){ for (int i=1;i<=cot[cur];i++) dfs2(cur+1,p+W[lst[cur][i]],t+C[lst[cur][i]]); }else dfs2(cur+1,p,t); } inline ll Solve(){ for (int i=0;i<7;i++) cot[i]=0; for (int i=1;i<=n;i++) lst[S[i]][++cot[S[i]]]=i; for (int j=0;j<7;j++) if (!cot[j]) return 1LL<<60; int mint0,mint1=1<<30,k; for (int i=0;i<(1<<7);i++){ int t[2]={1,1}; for (int j=0;j<7;j++) t[i>>j&1]*=cot[j]; if (max(t[0],t[1])<max(mint0,mint1)) mint0=t[0],mint1=t[1],k=i; } for (int j=0;j<7;j++) clr[j]=k>>j&1; tot=0; dfs1(0,0,0); sort(rec+1,rec+tot+1); int pnt=0; for (int i=1;i<=tot;i++) if (!pnt || rec[i].t<=rec[pnt].t) rec[++pnt]=rec[i]; tot=pnt; ret=1LL<<60; dfs2(0,0,0); return ret; } int sx ,icnt; int mapping ; inline int Bin(int x){ return lower_bound(sx+1,sx+icnt+1,x)-sx; } int main(){ const int Test=1000; int Q; srand(10086); freopen("t.in","r",stdin); freopen("t.out","w",stdout); read(Q); while (Q--){ read(n); read(m); icnt=0; for (int i=1;i<=n;i++) read(S[i]),read(W[i]),read(C[i]),Clr[i]=S[i],sx[++icnt]=S[i]; sort(sx+1,sx+icnt+1); icnt=unique(sx+1,sx+icnt+1)-sx-1; Ans=1LL<<60; for (int t=1;t<=Test;t++){ for (int i=1;i<=icnt;i++) mapping[i]=rand()%7; for (int i=1;i<=n;i++) S[i]=mapping[Bin(Clr[i])]; //for (int i=1;i<=n;i++) S[i]=rand()%7; Ans=min(Ans,Solve()); } Ans==1LL<<60?printf("-1\n"):printf("%lld\n",Ans); } return 0; }
相关文章推荐
- HDU 5355 Cake(2015多校第六场,搜索 + 剪枝)
- 【bzoj4800】[Ceoi2015]Ice Hockey World Championship 折半搜索
- HDU 5235 Friends (2015 Multi-University Training Contest 2 搜索+剪枝)
- HDU 5235 Friends (2015 Multi-University Training Contest 2 搜索+剪枝)
- HDU 5355 Cake(2015多校第六场,搜索 + 剪枝)
- 【BZOJ4325】NOIP2015 斗地主 搜索+剪枝
- 【BZOJ4325】NOIP2015 斗地主【搜索】【剪枝】
- 关于百度地图poi和geo搜索服务的应用
- Google正在研究手机用搜索服务
- 剪枝搜索心得
- 高德地图web服务api--搜索功能(输入提示)
- HDOJ 4277 USACO ORZ 搜索 剪枝
- Solr搜索服务架构图
- 《BREW进阶与精通――3G移动增值业务的运营、定制与开发》连载之31---LBS基于BREW的位置服务
- Web服务搜索与执行引擎 ----背景和意义及相关技术
- 百度开始做收费搜索服务
- 谷歌推出针对中国用户的团购搜索服务
- 剑指offer 面试题29:数组中出现次数超过一半的数字及其变形(腾讯2015秋招 编程题4)
- 【POJ1568】【极大极小搜索+alpha-beta剪枝】Find the Winning Move
- [lucene]使用lucene建立网站搜索服务