• 【洛谷】P4202 [NOI2008]奥运物流


    【洛谷】P4202 [NOI2008]奥运物流

    感觉有点降智

    首先设环长为(len),很容易推导出

    [R(1) = frac{sum_{i = 1}^{N} C_{i} k^{dep[i]}}{1 - k^{len}} ]

    我好像觉得似乎(len)越大底下越小了,太降智了,len越大底下越大

    所以环长越小越好,所以我们如果动了一条环边,就是把它尽量往1连

    枚举环上,强制要求环上上的点不选,除开1到1的后继的那条边,我们就获得了一棵树

    我们希望(dp)出改了m个点最大是多少,显然改就一定直接连到1

    (f[u][j][d])(u)这个点,子树里改了(j)个点,我们硬点(u)(1)的距离是(d)

    转移的话分(u)有没有被连到1

    如果被连到1了,那么就从(max(f[v][k][1],f[v][k][2]))转移过来,要加上(C_{u} imes K)

    否则就从(max(f[v][k][d + 1],f[v][k][1]))转移过来,要加上(C_{u} imes K^{d})

    第二维是个背包,直接做就行了

    #include <bits/stdc++.h>
    #define fi first
    #define se second
    #define pii pair<int,int>
    #define mp make_pair
    #define pb push_back
    #define space putchar(' ')
    #define enter putchar('
    ')
    #define eps 1e-10
    #define ba 47
    #define MAXN 5005
    //#define ivorysi
    using namespace std;
    typedef long long int64;
    typedef unsigned int u32;
    typedef double db;
    template<class T>
    void read(T &res) {
        res = 0;T f = 1;char c = getchar();
        while(c < '0' || c > '9') {
    	if(c == '-') f = -1;
    	c = getchar();
        }
        while(c >= '0' && c <= '9') {
    	res = res * 10 +c - '0';
    	c = getchar();
        }
        res *= f;
    }
    template<class T>
    void out(T x) {
        if(x < 0) {x = -x;putchar('-');}
        if(x >= 10) {
    	out(x / 10);
        }
        putchar('0' + x % 10);
    }
    int N,M;
    int fa[65];
    db K[65],C[65],f[65][65][65],g[65];
    bool nouse[65];
    void dfs(int u,int dep) {
        for(int v = 2 ; v <= N ; ++v) {
    	if(fa[v] == u) dfs(v,dep + 1);
        }
        for(int d = dep ; d >= min(dep,2) ; --d) {
    	memset(g,0,sizeof(g));
    	for(int v = 1 ; v <= N ; ++v) {
    	    if(fa[v] == u) {
    		for(int j = M ; j >= 0 ; --j) {
    		    for(int k = j ; k >= 0 ; --k) {
    			g[j] = max(g[j],g[k] + max(f[v][j - k][d + 1],f[v][j - k][1]));
    		    }
    		}
    	    }
    	}
    	for(int j = 0 ; j <= M ; ++j) f[u][j][d] = g[j] + C[u] * K[d];
        }
        if(!nouse[u] && fa[u] != 1) {
    	memset(g,0,sizeof(g));
    	for(int v = 1 ; v <= N ; ++v) {
    	    if(fa[v] == u) {
    		for(int j = M ; j >= 0 ; --j) {
    		    for(int k = j; k >= 0 ; --k) {
    			g[j] = max(g[j],g[k] + max(f[v][j - k][2],f[v][j - k][1]));
    		    }
    		}
    	    }
    	}
    	for(int j = 0 ; j < M ; ++j) f[u][j + 1][1] = g[j] + C[u] * K[1];
        }
    }
    void Init() {
        read(N);read(M);scanf("%lf",&K[1]);
        for(int i = 1 ; i <= N ; ++i) {
    	read(fa[i]);
        }
        K[0] = 1;
        for(int i = 2 ; i <= N ; ++i) {
    	K[i] = K[i - 1] * K[1];
        }
        for(int i = 1 ; i <= N ; ++i) {
    	scanf("%lf",&C[i]);
        }
    }
    void Solve() {
        int p = 1;
        db ans = 0;
        for(int len = 2 ; len ; ++len) {
    	p = fa[p];
    	if(p == 1) break;
    	memset(nouse,0,sizeof(nouse));
    	int t = 1,l = 0;
    	while(l != len) {
    	    nouse[t] = 1;
    	    t = fa[t];
    	    ++l;
    	}
    	int rec = 0;
    	if(fa[p] != 1) {--M;rec = fa[p];fa[p] = 1;}
    	memset(f,0,sizeof(f));
    	dfs(1,0);
    	db res = f[1][M][0] / (1 - K[len]);
    	ans = max(ans,res);
    	if(rec) {++M;fa[p] = rec;}
    	
        }
        printf("%.2lf
    ",ans);
    }
    int main(){
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Init();
        Solve();
    }
    
  • 相关阅读:
    PostThreadMessage
    WaitForSingleObject函数的使用
    CodeWarrior环境下中断使用
    Activity跳转时生命周期跟踪
    win7 VS2012+openCV-2.4.11 配置
    CodeBlocks16.01+wxWidgets3.0.2
    MFC一个类访问另一个类成员对象的成员变量值
    无法打开包括文件:'atlrx.h'的解决办法
    STM32f103的数电采集电路的TIMER定时器的使用与时序控制的程序
    STM32f103的数电采集电路的双ADC的设计与使用
  • 原文地址:https://www.cnblogs.com/ivorysi/p/11014812.html
Copyright © 2020-2023  润新知