dp记录

https://www.luogu.com.cn/training/5011#problems

P1049:

把剩余量转换成最大装多少,然后化为01背包

CF414B:

清新。先设\(f[i][j]\)表示在\(i\)位置填\(j\)的最大方案数。

for(int i = 2; i <= k; i++){
		for(int j = 1; j <= n; j++){
			for(int kk = 1; kk <= j; kk++){
				if(j % kk == 0){
					dp[i][j] += dp[i-1][kk];
					dp[i][j] %= MOD;	
				}
			}
		}
	}

\(O(n^3)\)会TLE。考虑因为当前数应是前一个数的倍数,因为 kk循环可以使用倍数 来减少循环。

for(int i = 2; i <= k; i++){
		for(int j = 1; j <= n; j++){
			for(int kk = 1; kk * j <= n; kk++){
				f[i][kk*j] = (f[i][kk * j] + f[i-1][j]) % MOD;
			}
		}
	}

P1586

完全背包,\(n^2\)预处理,\(O(1)\)查询

for(int i = 1; i * i <= 32768; i++){
		for(int j = i*i; j <= 32768; j++){
			for(int k = 1; k <= 4; k++){
				dp[j][k] += dp[j-i*i][k-1];
			}
		}
	}

P2426

\(dp[i][j]\)表示第i个数分了j段的最大值
则有\(max(dp[i][k], dp[j-1][k-1] + abs(a[i] - a[j]) * (i-j+1))\)

for(int i = 1; i <= n; i++){
		for(int j = 1; j <= i; j++){ // j ~ i 一段 
			for(int k = 1; k <= j; k++){
				if(i == j)	dp[i][k] = max(dp[i][k], a[i] + dp[i-1][k-1]);
				else dp[i][k] = max(dp[i][k], dp[j-1][k-1] + abs(a[i] - a[j]) * (i-j+1));
			}
		}
	}

跑的飞快,人生第一次进最优解第一页:https://www.luogu.com.cn/record/list?pid=P2426&orderBy=1&status=&page=1

P1387

wtcl\(if (a[i][j]==1) f[i][j]=min(min(f[i][j-1],f[i-1] [j]),f[i-1][j-1])+1;\)

我本来还想想P2058那样子

P1681同理

P2513

不会推柿子。。。。好吧是前缀和优化DP
https://www.luogu.com.cn/blog/user13091/solution-p2513

P1832

点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define int long long

int prime[100005];
int f[100004];


signed main(){
	int n;
	cin>>n;
	for(int i = 2; i <= n; i++){
		if(prime[i])	continue;
		for(int j = 1; j * i <= n; j++){
			prime[i*j] = true;
		}
		prime[i] = false;
	}	
	// for(int i = 1; i <= n; i++){
		// if(prime[i])	cout<<i<<' ';
	// }cout<<endl;
	f[0] = 1;
	for(int i = 2; i <= n; i++){
		if(prime[i])	continue;
		for(int j = 0; j + i <= n; j++){
			if(f[j]){
				f[j+i] += f[j];
			}
		}
	}
	cout<<f[n]<<endl;
	return 0;
}

P1510 精卫填海

点击查看代码
#include<bits/stdc++.h>
using namespace std;
int vv[10005], w[10005];
int f[10005];
int main(){
	int v, n ,c;
	cin>>v>>n>>c;
	for(int i = 1; i <= n; i++){
		cin>>vv[i]>>w[i];
	}
	for(int i = 1; i <= n; i++){
		for(int j = c; j >= w[i]; j--){
			f[j] = max(f[j], f[j-w[i]] + vv[i]);
		}
	}
	for(int i = 0; i <= v; i++){
		if(f[i] >= v){
			cout<<c-i<<endl;
			return 0;
		}
	}
	cout<<"Impossible"<<endl;
	return 0;
}
posted @ 2021-12-17 22:12  WRuperD  阅读(17)  评论(0编辑  收藏  举报

本文作者:DIVMonster

本文链接:https://www.cnblogs.com/guangzan/p/12886111.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

这是一条自定义内容

这是一条自定义内容