• CF1519F


    水博客了。

    先考虑确定宝箱之后怎么检查,可以 (2^n) 检查,然而是可以建立网络流的模型的,对于每个锁,连接宝箱 (i o) 钥匙 (j) 的一条边,然后每个宝箱连接 (S) 流量 (a_i),每个钥匙连接 (T) 流量 (b_i)

    可以发现如果最大流为 (sum a_i) 那么就说明非法,这意味着左部满流。

    发现流量非常小,我们考虑暴力一点来描述最大流:

    给每条边指定流量,满足每个点流出为 (a_i)(均满流),然后检查流入序列 ({c}),如果对于任意 (i) 均有 (c_ile b_i) 则合法,然后将所有流量非 (0) 的边加入答案。

    我们考虑到 (5^6=15625),而每个点流出的方案又只有 (inom{9}{4}(frac{1}{(1-x)^6}[x^4])=126) 种,于是对此大力 dp 的复杂度是可以接受的。

    总体复杂度 (mathcal O(prod b_i(sum inom{a_i+m-1}{m}))),我这里 DFS 转移的部分额外附带了一个 (m),大概是 (mathcal O(mprod (b_i+1)(sum inom{a_i+m-1}{m})))

    (Code:)

    #include<bits/stdc++.h>
    using namespace std ;
    #define Next( i, x ) for( int i = head[x]; i; i = e[i].next )
    #define rep( i, s, t ) for( int i = (s); i <= (t); ++ i )
    #define drep( i, s, t ) for( int i = (t); i >= (s); -- i )
    #define mp make_pair
    #define pi pair<int, int>
    #define pb push_back
    #define vi vector<int>
    int gi() {
    	char cc = getchar() ; int cn = 0, flus = 1 ;
    	while( cc < '0' || cc > '9' ) {  if( cc == '-' ) flus = - flus ; cc = getchar() ; }
    	while( cc >= '0' && cc <= '9' )  cn = cn * 10 + cc - '0', cc = getchar() ;
    	return cn * flus ;
    }
    const int N = 7 ; 
    const int M = 2e4 + 5 ; 
    const int inf = 4e8 ; 
    vector<int> f[M] ; 
    int n, m, fac[N], a[N], b[N], w[N][N], d[N], dp[N][M] ; 
    void dfs(int x, int y, int c, int C) {
    	if(x == m) {
    		if(c > d[m]) return ; 
    		int s = 0 ; d[m] -= c ; 
    		rep( i, 1, m ) s += d[i] * fac[i] ; 
    		dp[y][s] = min(dp[y][s], C + (c > 0) * w[y][m]) ; 
    		d[m] += c ; 
    		return ; 
    	}
    	rep( i, 0, min(d[x], c) ) {
    		d[x] -= i ; 
    		if(!i) dfs(x + 1, y, c, C) ;
    		else dfs(x + 1, y, c - i, C + w[y][x]) ;
    		d[x] += i ; 
    	}
    }
    signed main()
    {
    	n = gi(), m = gi() ; 
    	rep( i, 1, n ) a[i] = gi() ; 
    	rep( i, 1, m ) b[i] = gi() ; 
    	rep( i, 1, n ) rep( j, 1, m ) w[i][j] = gi() ; 
    	fac[1] = 1 ; int S = 0 ; 
    	rep( i, 2, m ) fac[i] = fac[i - 1] * (1 + b[i - 1]) ; 
    	rep( i, 1, m ) S += fac[i] * b[i] ; 
    	memset(dp, 63, sizeof(dp)), dp[0][S] = 0 ; 
    	for(int x = 1; x <= n; ++ x) {
    		rep( t, 0, S ) {
    			int u = t ; 
    			drep( i, 1, m ) d[i] = (u / fac[i]), u %= fac[i] ; 
    			dfs(1, x, a[x], dp[x - 1][t]) ; 
    		}
    	}
    	int ans = inf ; 
    	rep( x, 0, S ) ans = min(ans, dp[n][x]) ;
    	if(ans < inf) cout << ans << endl ; 
    	else puts("-1") ; 
    	return 0 ; 
    }
    
  • 相关阅读:
    C# 文本,图片 与 Base64的相互转换
    vue3.x 中的自定义组件及使用
    vue 的TodoList 小Demo
    vue中的条件渲染 v-show、v-if、v-else、v-else-if
    vue 使用$refs获取表单内容及v-model双向数据绑定
    python-异常处理&操作数据库&网络编程
    python-接口开发
    python-数据库&邮件
    python-函数和模块
    python-函数&list&dic&集合&文件读取
  • 原文地址:https://www.cnblogs.com/Soulist/p/14727439.html
Copyright © 2020-2023  润新知