zoukankan      html  css  js  c++  java
  • [Codeforces626F] Group Projects (DP)

    Group Projects


    Description

    There are n students in a class working on group projects. The students will divide into groups (some students may be in groups alone), work on their independent pieces, and then discuss the results together. It takes the i-th student ai minutes to finish his/her independent piece.

    If students work at different paces, it can be frustrating for the faster students and stressful for the slower ones. In particular, the imbalance of a group is defined as the maximum ai in the group minus the minimum ai in the group. Note that a group containing a single student has an imbalance of 0. How many ways are there for the students to divide into groups so that the total imbalance of all groups is at most k?

    Two divisions are considered distinct if there exists a pair of students who work in the same group in one division but different groups in the other.

    Input

    The first line contains two space-separated integers n and k (1 ≤ n ≤ 200, 0 ≤ k ≤ 1000) — the number of students and the maximum total imbalance allowed, respectively.

    The second line contains n space-separated integers ai (1 ≤ ai ≤ 500) — the time it takes the i-th student to complete his/her independent piece of work.

    Output

    Print a single integer, the number of ways the students can form groups. As the answer may be large, print its value modulo (10^9 + 7).

    Sample Input

    3 2
    2 4 5

    Sample Output

    3


    题目大意

    有n个商品,每个商品有不同的价值。要求把这些商品分组,每组有一个值为组内商品的最大价值差,问是这些每组值的和不超过m的方案数,答案对(1e9+7)取模。

    这道题的定义比较难,首先我们我们对商品按其价值由小到大进行排序。我们可以发现,每一组的价值差为相邻商品价值差的和。
    定义dp[i][j][k]表示前i件商品还有j组未完成,差值为k的分组种数。
    共有4种转移方案

    temp = (a[i] - a[i-1]) * j;

    1. 第i件商品加入一个新分组,并且该分组未完成; dp[i][j+1][k] = dp[i][j+1][k] + dp[i-1][j][k-temp];
    2. 第i件商品加入一个新分组,并且该分组只有一个元素;dp[i][j][k] = dp[i][j][k] + dp[i-1][j][k-temp];
    3. 第i件商品加入一个之前的分组,并且该分组未完成; dp[i][j][k] = dp[i][j][k] + dp[i-1][j][k-temp] * j;
    4. 第i件商品加入一个之前的分组,并且该分组已完成。 dp[i][j-1][k] = dp[i][j-1][k] + dp[i-1][j][k-temp] * j;

    每一个转移都只与i 和 i-1有关,所以我们可以用滚动数组进行优化,
    时间复杂度为(O(n^2k)), 空间复杂度为(nk).

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    const int mod = 1e9 + 7;
    int n,m;
    int dp[2][210][1010];
    int a[210];
    
    int main(){
    	ios::sync_with_stdio(false); cin.tie(0);
    	cin >> n >> m;
    	for(int i = 1;i <= n;i++)cin >> a[i];
    	sort(a + 1,a + n + 1);
    	
    	dp[0][0][0] = 1;
    	int cur = 0;
    	for(int i = 1;i <= n;i++){
    		cur ^= 1;
    		memset(dp[cur],0,sizeof(dp[cur]));
    		int v = a[i] - a[i-1];
    		for(int j = 0;j < i;j++){
    			int temp = v * j;
    			for(int k = temp;k <= m;k++){
    				dp[cur][j + 1][k] = (dp[cur][j + 1][k] + dp[cur^1][j][k-temp]) % mod;
    				dp[cur][j][k] = (dp[cur][j][k] + dp[cur^1][j][k-temp]) % mod;
    				if(j)dp[cur][j-1][k] = (dp[cur][j-1][k] + (long long)dp[cur^1][j][k-temp] * j) % mod;
    				if(j)dp[cur][j][k] = (dp[cur][j][k] + (long long)dp[cur^1][j][k-temp] * j) % mod;
    			}
    		}
    	}
    	int ans = 0;
    	for(int i = 0;i <= m;i++)
    		ans = (ans + dp[cur][0][i]) % mod;
    	cout << ans << endl;
    	return 0;
    }
    
  • 相关阅读:
    奋力拼搏,永不言弃
    软件工程最终总结
    人生第一次JAVA编程,电梯(并不算完成版),以及IDEA里使用git
    尝试单元测试
    作业2的回答
    word count程序,以及困扰人的宽字符与字符
    关于未成品的问题:字符类型和其他种种
    随手一写,简单的四则运算练习
    浏览器缓存分析
    Codeforces Round #582 (Div. 3)
  • 原文地址:https://www.cnblogs.com/ZegWe/p/5952886.html
Copyright © 2011-2022 走看看