zoukankan      html  css  js  c++  java
  • [BJOI2019]奥术神杖(分数规划,动态规划,AC自动机)

    [BJOI2019]奥术神杖(分数规划,动态规划,AC自动机)

    题面

    洛谷

    题解

    首先乘法取(log)变加法,开(c)次根变成除(c)
    于是问题等价于最大化(displaystyle frac{sum val_i}{c})。典型的分数规划的形式。
    二分权值(k),每个点的点权变成(val_i-k),转为求最值,那么直接在(AC)自动机上(dp)就行了。
    注意精度问题。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    using namespace std;
    #define MAX 1505
    inline int read()
    {
    	int x=0;bool t=false;char ch=getchar();
    	while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    	if(ch=='-')t=true,ch=getchar();
    	while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    	return t?-x:x;
    }
    struct Node{int son[10],ff,s;double w;}t[MAX];
    int tot;
    void Insert(char *s,int val)
    {
    	int l=strlen(s+1),u=0;
    	for(int i=1;i<=l;++i)
    	{
    		int c=s[i]-48;
    		if(!t[u].son[c])t[u].son[c]=++tot;
    		u=t[u].son[c];
    	}
    	t[u].w=log(val);t[u].s+=1;
    }
    int Q[MAX],L,R;
    void BuildFail()
    {
    	L=1;
    	for(int i=0;i<10;++i)if(t[0].son[i])Q[++R]=t[0].son[i];
    	while(L<=R)
    	{
    		int u=Q[L++];t[u].w+=t[t[u].ff].w;t[u].s+=t[t[u].ff].s;
    		for(int i=0;i<10;++i)
    			if(t[u].son[i])t[t[u].son[i]].ff=t[t[u].ff].son[i],Q[++R]=t[u].son[i];
    			else t[u].son[i]=t[t[u].ff].son[i];
    	}
    }
    char T[MAX],S[MAX];int n,m;
    double f[MAX][MAX];int g1[MAX][MAX],g2[MAX][MAX];
    void Tr(int i,int j,int k)
    {
    	int v=t[j].son[k];
    	if(f[i][v]<f[i-1][j]+t[v].w)
    	{
    		f[i][v]=f[i-1][j]+t[v].w;
    		g1[i][v]=j;g2[i][v]=k;
    	}
    }
    bool check(double K)
    {
    	for(int i=0;i<=tot;++i)t[i].w-=K*t[i].s;
    	int len=strlen(T+1);
    	for(int i=0;i<=len;++i)
    		for(int j=0;j<=tot;++j)f[i][j]=-1e300;
    	f[0][0]=0;
    	for(int i=1;i<=len;++i)
    		for(int j=0;j<=tot;++j)
    				if(T[i]=='.')for(int k=0;k<10;++k)Tr(i,j,k);
    				else Tr(i,j,T[i]-48);
    	double ans=-1e300;
    	for(int i=1;i<=tot;++i)ans=max(ans,f[len][i]);
    	for(int i=0;i<=tot;++i)t[i].w+=K*t[i].s;
    	return ans>0;
    }
    int main()
    {
    	n=read();m=read();
    	scanf("%s",T+1);
    	for(int i=1,v;i<=m;++i)scanf("%s",S+1),v=read(),Insert(S,v);
    	BuildFail();
    	double l=0,r=21;
    	while(r-l>1e-3)
    	{
    		double mid=(l+r)/2;
    		if(check(mid))l=mid;
    		else r=mid;
    	}
    	check(l);int pos=0,len=strlen(T+1);
    	for(int i=1;i<=tot;++i)if(f[len][i]>f[len][pos])pos=i;
    	for(int i=len;i;--i)S[i]=g2[i][pos]+48,pos=g1[i][pos];
    	for(int i=1;i<=len;++i)putchar(S[i]);puts("");
    	return 0;
    }
    
  • 相关阅读:
    【Salesfoece】Apex基础数据类型
    【Javascript】Redux ,Saga关系
    【CSS】选择器
    爬取取百度和Flickr图像
    hadoop系列之一问题锦集
    进行数据清洗_在进行大数据分析之前都需要进行数据清洗,如何进行数据清洗?...
    Hadoop中文编码乱码相关问题
    Can not find the tag library descriptor for "http://java.sun.com/jsp/jstl/
    解决:Multiple annotations found at this line:
    HttpServletRequest cannot be resolved to a type解决方案
  • 原文地址:https://www.cnblogs.com/cjyyb/p/10746339.html
Copyright © 2011-2022 走看看