HDU 5800 To My Girlfriend (动态规划)

题目链接:HDU 5800

题面:

To My Girlfriend

Time Limit: 2000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)

Total Submission(s): 737    Accepted Submission(s): 292

Problem Description

Dear Guo

I never forget the moment I met with you.You carefully asked me: "I have a very difficult problem. Can you teach me?".I replied with a smile, "of course"."I have n items, their weight was a[i]",you said,"Let‘s define f(i,j,k,l,m) to be the number of the subset
of the weight of n items was m in total and has No.i and No.j items without No.k and No.l items.""And then," I asked.You said:"I want to know

∑i=1n∑j=1n∑k=1n∑l=1n∑m=1sf(i,j,k,l,m)(i,j,k,laredifferent)

Sincerely yours,

Liao

Input

The first line of input contains an integer T(T≤15)
indicating the number of test cases.

Each case contains 2 integers n,
s
(4≤n≤1000,1≤s≤1000).
The next line contains n numbers: a1,a2,…,an
(1≤ai≤1000).

Output

Each case print the only number — the number of her would modulo
109+7
(both Liao and Guo like the number).

Sample Input

2
4 4
1 2 3 4
4 4
1 2 3 4

Sample Output

8
8

Author

UESTC

Source

2016 Multi-University Training Contest 6

题意:

吐槽下题意,很难懂。求的是,给定n个数,其中选定若干数,这若干数的权值和为m,且这些数中没有下标为i,j的数,有下标为k,l的数的集合个数。

解题:

dp[i][j][s1][s2],代表的是前i个物品,总权值为j,已有s1个必选,s2必不选的方案数。那么对于当前一个状态,它有四种转移状态。

1.选中当前的,增加权值,增加必选个数。

2.选择当前的,增加权值,不增加必选个数。

3.不选中当前的,不增加权值,增加不必选个数。

4.不选中当前的,不增加权值,不增加必选个数。

因为i,j可以互换,l,k也可以互换,故而最后方案数乘以4即为所求。

代码:

#include <iostream>
#include <iomanip>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define mod 1000000007
#define LL long long
#define p(a) printf("%d\n",a)
using namespace std;
unsigned dp[1005][1005][3][3];
int a[1005];
int main()
{
    int t,n,s,tmp;
	LL ans;
	scanf("%d",&t);
	while(t--)
	{
        ans=0;
		scanf("%d%d",&n,&s);
		for(int i=1;i<=n;i++)
		  scanf("%d",&a[i]);
		memset(dp,0,sizeof(dp));
		dp[1][a[1]][0][0]=1;
		dp[1][a[1]][1][0]=1;
		dp[1][0][0][0]=1;
		dp[1][0][0][1]=1;
		for(int i=2;i<=n;i++)
		{
			for(int j=0;j<=s;j++)
			{
               tmp=j+a[i];
			   if(tmp<=s)
			   {
				   for(int k=0;k<=2;k++)
				   {
					   dp[i][tmp][0][k]=(dp[i][tmp][0][k]+dp[i-1][j][0][k])%mod;
					   dp[i][tmp][1][k]=(dp[i][tmp][1][k]+dp[i-1][j][0][k])%mod;
					   dp[i][tmp][1][k]=(dp[i][tmp][1][k]+dp[i-1][j][1][k])%mod;
					   dp[i][tmp][2][k]=(dp[i][tmp][2][k]+dp[i-1][j][1][k])%mod;
					   dp[i][tmp][2][k]=(dp[i][tmp][2][k]+dp[i-1][j][2][k])%mod;

				   }
			   }
			   for(int k=0;k<=2;k++)
			   {
				   dp[i][j][k][0]=(dp[i][j][k][0]+dp[i-1][j][k][0])%mod;
				   dp[i][j][k][1]=(dp[i][j][k][1]+dp[i-1][j][k][0])%mod;
				   dp[i][j][k][1]=(dp[i][j][k][1]+dp[i-1][j][k][1])%mod;
				   dp[i][j][k][2]=(dp[i][j][k][2]+dp[i-1][j][k][1])%mod;
				   dp[i][j][k][2]=(dp[i][j][k][2]+dp[i-1][j][k][2])%mod;
			   }
			}
		}
		for(int i=1;i<=s;i++)
			ans=(ans+dp[n][i][2][2])%mod;
		printf("%lld\n",ans*4%mod);
	}
	return 0;
}  
时间: 2025-01-14 05:28:45

HDU 5800 To My Girlfriend (动态规划)的相关文章

hdu 5800 To My Girlfriend + dp

传送门:hdu 5800 To My Girlfriend 题意:给定n个物品,其中i,j必选,l,m必不选,问组成体积为s的方法一共有多少种 思路:定义dp[i][j][s1][s2],表示前i种物品能够构成的体积为j,其中有s1种定为必选,s2种定为不必选;因为递推到第i层时,只与第i-1层有关,所以把第一维降到2来省内存.然后就是dp[i][j][s1][s2]=dp[i-1][j][s1][s2]+dp[i-1][j][s1][s2-1]+dp[i-1][j-a[i]][s1-1][s2

HDU 5800 To My Girlfriend

题目:To My Girlfriend 链接:http://acm.hdu.edu.cn/showproblem.php?pid=5800 题意: 给你n.s,接下来n个数,定义 f ( i , j , k , l , m )表示下标为i.j的必选,k.l的必不选,且和为m的 子集 数量. 然后求上图式子的值. 思路: 刚开始想着i 个数的和小于等于s 的子集数量,定义了dp[i][j]表示i 个数,和为j 的情况数量,不管怎么优化死活要n^3级别.看了题解,才觉醒... 定义dp[i][j][

HDU 5800 To My Girlfriend(单调DP)

[题目链接]http://acm.hdu.edu.cn/showproblem.php?pid=5800 [题目大意] 给出一个容量上限s,f[i][j][k][l][m]表示k和l两个物品不能选,i和j两个物品必选,最终质量为m的方案数.求这些方案数的总和. [题解] 令dp[i][j][s1][s2]表示前i个物品填了j的体积,有s1个物品选为为必选,s2个物品选为必不选的方案数(0<=s1,s2<=2),则有转移方程dp[i][j][s1][s2]=dp[i-1][j][s1][s2]+

HDU 5800 (DP)

Problem To My Girlfriend (HDU 5800) 题目大意 给定一个由n个元素组成的序列,和s (n<=1000,s<=1000) 求 :   f (i,j,k,l,m) 指必定选第i,j号元素,必定不选k,l号元素,选的元素总和为m的子集个数. 解题分析 一开始想了个n^3的DP,f[j][k]表示选j个数总和为k的方案数,然后一直想着怎么去优化,陷进死胡同,到比赛结束还没想出来. 看了题解后,感觉智商被藐视了. 题解的做法是f[i][j][s1][s2]表示前i个数总

HDU 1160 FatMouse&#39;s Speed 动态规划 记录路径的最长上升子序列变形

题目大意:输入数据直到文件结束,每行两个数据 体重M 和 速度V,将其排列得到一个序列,要求为:体重越大 速度越低(相等则不符合条件).求这种序列最长的长度,并输出路径.答案不唯一,输出任意一种就好了. 题目思路:这是个最长上升子序列的问题,我们按W的升序进行排序,若W相等则按V的降序排序.用Pre[]记录当前点的前驱节点,Last记录序列最后一个点,maxn记录最长长度,完成动规后可根据Last和Pre[]输出路径. #include<cstdio> #include<stdio.h&

HDU 1505 Largest Rectangle in a Histogram &amp;&amp; HDU 1506 City Game(动态规划)

1506题意:给你连续的直方图(底边边长为1),求连续的矩阵面积. 对每个直方图,分别向左向右进行扩展. #include<cstdio> #include<stdlib.h> #include<string.h> #include<string> #include<map> #include<cmath> #include<iostream> #include <queue> #include <sta

HDU 4336 Card Collector(动态规划-概率DP)

Card Collector Problem Description In your childhood, do you crazy for collecting the beautiful cards in the snacks? They said that, for example, if you collect all the 108 people in the famous novel Water Margin, you will win an amazing award. As a

HDU 1003 Max Sum【动态规划求最大子序列和详解 】

Max Sum Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 250714    Accepted Submission(s): 59365 Problem Description Given a sequence a[1],a[2],a[3]......a[n], your job is to calculate the max su

hdu 4939 Stupid Tower Defense 动态规划

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4939 塔防游戏 红塔绿塔蓝塔 当年我队友在不知道红塔必须放最后这个结论的情况下把这道题做出来了现在我细思恐极 仰慕至极Orz 写出来不是很难的题目 但是仔细想想 还是有很多值得推敲的地方 下面证明一下这个“常识” 反证法 a.如果得到一个最优解 然后在这个最优解中有一个红塔在一个绿塔前面 那么把这两个塔交换一下位置 必定可以得到一个更优的解 与假设的“当前是最优解”矛盾 b.如果得到一个最优解 然后