zoukankan      html  css  js  c++  java
  • [CSP校内集训]v(记忆化搜索+map优化状压)

    题意

    有一个长为(n)的01序列,每次等概率从([1,len])中抽取一个(x),可以选择从右向左或是从左往右的第(x)个数字取走,求(k)次操作后取走1的期望个数((kleq nleq 30))

    思路

    然而就是直接状态压缩

    以24为分界线,24步以内用状态压缩;24步以上可以发现状态很大但状态数很少(因为只进行了几次操作),用(map)

    对于每种状态枚举(x)记忆化搜索即可,需要大力卡常

    二进制下去掉第(p)位:(x=((x>>p)<<(p-1)) | (x&((1<<p)-1)))

    Code

    (因为我的代码太菜了卡不过常数,所以放的别人的)

    #include<bits/stdc++.h>
    #define maxn 35
    #define LL long long
    using namespace std;
    int n,m,a[maxn];
    char s[maxn];
    double ans,f[(1<<24)+5];
    const double eps=1e-10;
    LL bin,num;
    map< LL,double > mp[31];
    
    inline void work(int x,int len)
    {
    	x=len-x+1;
    	int y=bin&((1<<(x-1))-1);
    	bin=((bin>>x)<<(x-1))|y;
    }
    
    double dfs(int now)
    {
    	if(now==m+1 || bin==0) return 0.0;
    	double res=0.0; LL tmp=bin;
    	int len=n-now+1;
    	if(len<24 && f[1<<len|bin]!=-1) return f[1<<len|bin];
    	if(mp[now].count(bin)) return mp[now][bin];
    	for(int i=1;i<=(len+1)/2;i++)
    	{
    		double qwq=0.0;
    		int x=(bin>>(len-i))&1; work(i,len);
    		if((len&1) && i==(len+1)/2)
    			qwq=(x+dfs(now+1))*1.0/len;
    		else qwq=(x+dfs(now+1))*2.0/len;
    		bin=tmp;
    		x=(bin>>(len-(n-now+2-i)))&1; work(n-now+2-i,len);
    		if((len&1) && i==(len+1)/2)  
    			qwq=max(qwq,(x+dfs(now+1))*1.0/len);
    		else qwq=max(qwq,(x+dfs(now+1))*2.0/len);
    		bin=tmp;
    		res+=qwq;
    	}
    	if(len<24) return f[1<<len|bin]=res;
    	else return mp[now][bin]=res;
    }
    
    int main()
    {
    	freopen("v.in","r",stdin);
    	freopen("v.out","w",stdout);
    	scanf("%d%d%s",&n,&m,s+1);
    	for(int i=1;i<=n;i++) a[i]=(s[i]=='W')?1:0,bin=(bin<<1LL)|a[i]; 
    	for(int i=1;i<(1<<24);i++) f[i]=-1;
    	printf("%.10lf
    ",dfs(1));
    	return 0;
    }
    
  • 相关阅读:
    js5
    js4
    js(3)
    JS内容(2)
    html复习
    js介绍及内容(1)
    定位2
    position定位
    CSS
    列表及行块转变
  • 原文地址:https://www.cnblogs.com/Chtholly/p/11769100.html
Copyright © 2011-2022 走看看