zoukankan      html  css  js  c++  java
  • [SCOI2008]奖励关

    题面在这里

    题意

    不好描述.....大家还是看luogu上的吧(资磁洛谷!)

    sol

    (n<=15)的良心数据肯定是状压啦
    只是设状态的时候有点头疼
    首先思考我们在无法预知之后宝物的情况下如何求解
    对于第i个宝物,如果我们没有满足吃掉的条件的话就只能放弃(可惜...)
    如果我们能吃掉,那么就需要观察吃掉它和不吃掉它的期望哪个更高,从更优的期望中进行决策
    所以这样的思路让我们必须倒着DP
    (f[i][x])表示当前已经吃掉的宝物状态为x的时候,迎接第i个宝物,在最优决策下所能得到的期望
    之后按照上面的思路转移即可

    代码

    #include<bits/stdc++.h>
    #include<algorithm>
    #include<iostream>
    #include<cstdlib>
    #include<iomanip>
    #include<cstring>
    #include<vector>
    #include<cstdio>
    #include<string>
    #include<bitset>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<map>
    #include<set>
    #define mp make_pair
    #define pb push_back
    #define RG register
    #define il inline
    using namespace std;
    const int mod=1e9+7;
    const int N=16;
    const double eps=1e-10;
    typedef unsigned long long ull;
    typedef vector<int>VI;
    typedef long long ll;
    typedef double dd;
    il ll read(){
    	RG ll data=0,w=1;RG char ch=getchar();
    	while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    	if(ch=='-')w=-1,ch=getchar();
    	while(ch<='9'&&ch>='0')data=data*10+ch-48,ch=getchar();
    	return data*w;
    }
    
    dd f[105][65537];
    int k,n,p[N],need[N][N],g[65537];
    bool check[65537];
    
    il bool pd(int x){//判断一个状态是否为合法状态
    	for(RG int i=1;i<=n;i++)
    		if((x&(1<<(i-1)))==(1<<(i-1)))
    			for(RG int j=1;j<=need[i][0];j++)
    				if((x&(1<<(need[i][j]-1)))!=(1<<(need[i][j]-1)))
    					return 0;
    	return 1;
    }
    
    il void DP(){		
    	for(RG int i=k;i;i--)
    		for(RG int j=1,x=g[j];j<=g[0];j++,x=g[j]){
    			for(RG int a=1;a<=n;a++){
    				if(check[x|(1<<(a-1))]&&f[i+1][x|(1<<(a-1))]+p[a]>f[i+1][x]){
    					//在选择合法的情况下,吃掉更优
    					f[i][x]+=f[i+1][x|(1<<(a-1))]+p[a];
    				}
    				else f[i][x]+=f[i+1][x];//不能吃或不吃更优
    			}
    			f[i][x]/=n;
    		}
    }
    
    int main()
    {
    	k=read();n=read();
    	for(RG int i=1,x;i<=n;i++){
    		p[i]=read();
    		while(x=read())need[i][++need[i][0]]=x;
    	}
    
    	for(RG int i=0;i<(1<<n);i++)
    		if(check[i]=pd(i))g[++g[0]]=i;
        //预处理出所有合法状态
    
    	DP();
    	
    	printf("%.6lf
    ",f[1][0]);
    	return 0;
    }
    
    

    友链

    SYCdalao的题解见这里

  • 相关阅读:
    SpringCloud
    SpringCloud
    一个表的字段更新另一个表的字段
    MYSQL5.7 sql_mode=only_full_group_by
    CentOS7 防火墙操作
    log4j DailyRollingFileAppender, DatePattern 配置
    Fiddler抓包-会话框添加查看get与post请求类型选项
    Fiddler抓包-工具介绍(request和response)
    Fiddler抓包-get与post请求
    Fiddler抓包-只抓APP的请求
  • 原文地址:https://www.cnblogs.com/cjfdf/p/8405357.html
Copyright © 2011-2022 走看看