!CodeForces 543A Writing Code --DP--(三维dp,滚动数组)

题意:n个程序员一起写m行代码,第i个程序员每写一行有a[i]个bug,求总bug不超过b的分配方案有多少种

分析:这题很像完全背包,不过求的不是最大/最小bug数,求的是bug数小于上限的分配方案。所以这题要用三维dp

dp[i][j][k]表示前i个个程序员总共写了j行代码产生了k个bug时的plan数,这题有两种转移:1)第i个程序员再写一行;2)换第i+1号程序员写

所以方程:dp[i][j][k]=dp[i-1][j][k]+dp[i][j-1][k-a[i]],注意:程序员可能一行都没写

另外三维的数组会超内存,所以用滚动数组。滚动数组主要用于递推和dp,它正是利用了递推和dp的特性,原理是这样的:比如dp[i]=dp[i-1],也就是要求dp[i]只需要dp[i-1]的信息,所以前面的dp[i-k](k>1)的信息对于dp[i]来说都是没用的,滚动的意思就是不断把前面没用的信息用后面求出的有用的信息覆盖,节约空间。具体做法就是,dp[i]需要多少前面的信息就信息数加 一那么大的数组,比如dp[i][k]=dp[i-1][k]+dp[i-2][k],0<i<10000000,0<k<10,只需dp[3][11],方程改为:

dp[i%3]=dp[(i-1)%3][k]+dp[(i-2)%3][k]即可,还有另一种滚动数组的实现方法我还没懂,先把代码放在这。

注意理解这题跟完全背包和01背包的区别和联系

代码1:

#include<iostream>
using namespace std;
long long mod,dp[2][508][508];
int a[501];
int n,m,b;
int main()
{
        cin>>n>>m>>b>>mod;
		for(int i=1;i<=n;i++) cin>>a[i];
		for(int i=1;i<=n;i++) dp[i%2][0][0]=1;
		for(int i=1;i<=n;i++)
		   for(int j=1;j<=m;j++)
		      for(int k=0;k<=b;k++){
		         if(a[i]>k)  dp[i%2][j][k]=(dp[(i-1)%2][j][k])%mod;
		      	 else  dp[i%2][j][k]=(dp[(i-1)%2][j][k]+dp[i%2][j-1][k-a[i]])%mod;
		      }
		long long ans=0;
		for(int i=0;i<=b;i++) ans=(ans+dp[n%2][m][i])%mod;
		cout<<ans%mod<<endl;
}

代码2:

#include<iostream>
#include<cstring>
using namespace std;
long long mod,dp[508][508];
int a[501];
int n,m,b;
int main()
{
	while(cin>>n>>m>>b>>mod){
		for(int i=1;i<=n;i++) cin>>a[i];
		memset(dp,0,sizeof(dp));
		for(int i=0;i<=b;i++) dp[0][i]=1;
		for(int i=1;i<=n;i++)
		   for(int j=1;j<=m;j++)
		      for(int k=a[i];k<=b;k++){
		      	   dp[j][k]=(dp[j][k]+dp[j-1][k-a[i]])%mod;
		      }
		long long ans=0;cout<<dp[m][b]<<endl;
	}
}
时间: 2024-10-03 11:27:41

!CodeForces 543A Writing Code --DP--(三维dp,滚动数组)的相关文章

Codeforces 543A Writing Code

A. Writing Code Programmers working on a large project have just received a task to write exactly m lines of code. There are n programmers working on a project, the i-th of them makes exactly ai bugs in every line of code that he writes. Let's call a

CodeForces 543A - Writing Code DP 完全背包

有n个程序,这n个程序运作产生m行代码,但是每个程序产生的BUG总和不能超过b, 给出每个程序产生的代码,每行会产生ai个BUG,问在总BUG不超过b的情况下, 我们有几种选择方法思路:看懂了题意之后就是一个完全背包题了 定义dp[ i ][ j ][ k ] 表示前 i 个程序员,已经写了 j 行代码, 已经产生了 k 个 bugs . 根据题意,得知第 i 个程序员会写 r 行代码,那么相当于 dp[ i ][ j ][ k ] += dp[i - 1][j - r][k - ra[ i ]

2017 Hackatari Codeathon C. Arcade(DP)(滚动数组)

C. Arcade time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output Abdullah and Haritha were building a 3D printed arcade machine. Abdullah had worked on the hardware, while Haritha had been working

【SDOI】【DP】【滚动数组】【bzoj1925】地精部落

1925: [Sdoi2010]地精部落 Time Limit: 10 Sec  Memory Limit: 64 MB Submit: 814  Solved: 494 [Submit][Status][Discuss] Description 传说很久以前,大地上居住着一种神秘的生物:地精. 地精喜欢住在连绵不绝的山脉中.具体地说,一座长度为 N 的山脉 H可分 为从左到右的 N 段,每段有一个独一无二的高度 Hi,其中Hi是1到N 之间的正 整数. 如果一段山脉比所有与它相邻的山脉都高,则

字符串匹配dp+bitset,滚动数组优化——hdu5745(经典)

bitset的经典优化,即把可行性01数组的转移代价降低 bitset的适用情况,当内层状态只和外层状态的上一个状态相关,并且内层状态的相关距离是一个固定的数,可用bitset,换言之,能用滚动数组是能用bitset优化的前提 /* dp[i,j][0|1|2]表示p串的第i位,s串的第j位相匹配,pi和pi-1换,pi不换,pi和pi+1换的状态下是否能匹配 dp[i,j][0] = dp[i-1,j-1][2] & p[i-1]==s[j] dp[i,j][1] = (dp[i-1,j-1]

【概率dp】【滚动数组】CDOJ1652 都市大飙车

转移方程很显然. 因为是多段图模型,所以可以滚动数组优化一维空间. #include<cstdio> #include<cstring> using namespace std; int m,K,n,p; bool zaw[1010][30010]; double f[2][30010]; int main(){ int x,y; bool flag=1; scanf("%d%d%d%d",&m,&K,&n,&p); for(in

背包DP || Codeforces 544C Writing Code

程序员写bug的故事23333 题意:n个程序员,一共写m行程序,最多产生b个bug,问方案数 思路:f[i][j]表示写了i行,产生了j个bug的方案数,因为每个人都是可以独立的,所以i循环到n都做一遍 f[i][j] += f[i-1][j-a[i]] 在前一行  i 的 a[i] 个bug还没有写上去的情况数 #include <iostream> #include <cstdio> #include <algorithm> using namespace std

2015多校.Zero Escape (dp减枝 &amp;&amp; 滚动数组)

Zero Escape Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 289    Accepted Submission(s): 135 Problem Description Zero Escape, is a visual novel adventure video game directed by Kotaro Uchiko

01 背包基础 - 空间优化 (滚动数组,一维阵列)

2017-09-03 11:39:16 writer:pprp 以很简单的一个动态规划问题为引入: 从左上角到右下角走过的路径和最大,问你最大为多少? 1.可以想到普通的dp 状态转移为: dp[i][j] = max(dp[i-1][j],dp[i][j-1]) + arr[i][j]; 2.采用滚动数组的方式-节约了不必要的空间 状态转移为:dp2[i%2][j] = max(dp2[(i+1)%2][j],dp2[i%2][j-1]) + arr[i][j]; 3.采用一维阵列的方式更加节