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;
}