#动态规划
DP算法
Enki_Liu
这个作者很懒,什么都没留下…
展开
-
AcWing 1084. 数字游戏 II
[j+x+(…)]%P=k;[x+(…)]%P=(k-j)%P;#include<bits/stdc++.h>using namespace std;const int N = 15,M = 110;int f[N][N][M];//首位为j,共有i位的方案数,余数为kint P;//保证正数int mod(int a,int b){return (a%b+b)%b;}void init(){ memset(f,0,sizeof f); for(int原创 2021-09-27 21:07:25 · 110 阅读 · 0 评论 -
AcWing 1081. 度的数量
数位DP技巧:1.[X,Y]=>f[Y]-f[X]2.树的方式考虑问题(分类讨论)n能够表示成k个系数为1的b的幂次之和⟺n的b进制表示中恰好有k个1且其余位必须都是0#include<bits/stdc++.h>using namespace std;const int N = 35;int f[N][N];//从i位中选B进制中j的个数的方案数C(i,j)=C(i-1,j)+C(i-1,j-1)int K,B;//初始化f,void init(){原创 2021-09-27 01:28:12 · 90 阅读 · 0 评论 -
AcWing 1075. 数字转换
//将数和约数之和连成数,就转换成 AcWing 1072. 树的最长路径#include<bits/stdc++.h>using namespace std;const int N = 55000,M = 1e6;int h[N],e[M],ne[M],idx;int n,ans;void add(int a,int b){ e[idx]=b; ne[idx]=h[a]; h[a]=idx++;}int dfs_down(int u,int fa原创 2021-09-20 20:36:10 · 90 阅读 · 0 评论 -
AcWing 1073. 树的中心
//树的中心通过每个结点向下或向上走的最远路径#include<bits/stdc++.h>using namespace std;const int N = 10100,M = N*2;int h[N],e[M],ne[M],w[M],idx;int n;int up[M],d1[M],d2[M],path[M];void add(int a,int b,int c){ e[idx]=b; w[idx]=c; ne[idx]=h[a]; h[原创 2021-09-20 18:50:27 · 81 阅读 · 0 评论 -
AcWing 1072. 树的最长路径
//树的直径相当于一个节点其子节点的最长路径和次长路径之和#include<bits/stdc++.h>using namespace std;const int N = 10100,M=N*2;int h[N],e[M],w[M],ne[M],idx;int n,ans;//传一个father变量防止向上走int dfs(int u,int father){ //向下走的最大长度和次大长度 int d1=0,d2=0; for(int i=原创 2021-09-20 16:43:35 · 73 阅读 · 0 评论 -
AcWing 321. 棋盘分割
#include<bits/stdc++.h>using namespace std;const int N = 15, M = 9, INF = 1e9;int g[M][M];double f[M][M][M][M][N];//将(x1,y1)到(x2,y2)矩阵分割成k块所得最小均方差int n,m=8;double X;//平均值double get(int x1,int y1,int x2,int y2){ double sum=g[x2][y2]-g[x2原创 2021-09-20 16:13:21 · 90 阅读 · 0 评论 -
AcWing 479. 加分二叉树
#include<bits/stdc++.h>using namespace std;const int N = 33;int f[N][N];//二叉树i到j最高加分int g[N][N];//二叉树i到j的根节点int w[N];int n,score;//前序遍历void dfs(int l,int r){ if(l>r)return; int root=g[l][r]; cout<<root<<" ";原创 2021-09-17 15:28:27 · 97 阅读 · 0 评论 -
AcWing 1069. 凸多边形的划分
#include<bits/stdc++.h>using namespace std;typedef long long LL;const int N = 55,M = 40;LL f[N][N][M];int n;LL w[N]; void add(LL a[],LL b[]){ int t=0; static LL c[M]; memset(c,0,sizeof c); for(int i=0;i<M;i++) {原创 2021-09-17 14:27:53 · 106 阅读 · 0 评论 -
AcWing 320. 能量项链
#include<bits/stdc++.h>using namespace std;const int N = 220;int f[N][N];int a[N];int n;int main(){ cin>>n; for(int i=1;i<=n;i++) { int t; scanf("%d",&t); a[i]=a[i+n]=t; } a[0]=a[n];原创 2021-09-12 15:15:27 · 55 阅读 · 0 评论 -
AcWing 1068. 环形石子合并
#include<bits/stdc++.h>using namespace std;const int N = 440;int f1[N][N];//从第i位开始的n个数,j到k的最小代价int f2[N][N];//从第i位开始的n个数,j到k的最大代价int a[N],s[N],n;int main(){ cin>>n; for(int i=1;i<=n;i++) { int t; scanf(".原创 2021-09-12 14:21:33 · 55 阅读 · 0 评论 -
AcWing 292. 炮兵阵地
#include<bits/stdc++.h>using namespace std;const int N = 12,M =1<<N;vector<int> state;int f[2][M][M];//已经摆完第i行,且第i行状态是j,第i-1行状态是k的炮兵最大数量(MAX)int g[110],cnt[M];int n,m;bool check(int st){ for(int i=0;i<m;i++) {原创 2021-09-11 23:31:05 · 75 阅读 · 0 评论 -
AcWing 1052. 设计密码
#include<bits/stdc++.h>using namespace std;const int N = 55,MOD = 1e9+7;char str[N];int ne[N];int f[N][N];//对于前i个字符,匹配到str字符串的第j个位置(匹配成功说明包含子串),计算不包含子串的数量int n,m;int main(){ scanf("%d%s",&n,str+1); m=strlen(str+1); //ne原创 2021-08-11 17:57:51 · 228 阅读 · 0 评论 -
AcWing 1057. 股票买卖 IV
#include<bits/stdc++.h>using namespace std;const int N = 1e5+110,K = 110; int f[N][K][2];//f[i][0/1]表示前i天,共完成j次交易时获得的最大利润。//0表示当前未持有股票,1表示当前持有股票int w[N];int n,k;int main(){ scanf("%d%d",&n,&k); for(int i=1;i<=n;i++) .原创 2021-08-04 17:50:45 · 60 阅读 · 0 评论 -
AcWing 1049. 大盗阿福
#include<bits/stdc++.h>using namespace std;const int N = 1e5+10;int f[N],w[N];//f[i]:选择前i个店铺行窃获取的最大现金数量int n,T;int main(){ cin>>T; while(T--) { cin>>n; for(int i=1;i<=n;i++) scanf("%d",&w原创 2021-08-04 16:46:58 · 76 阅读 · 0 评论 -
AcWing 734. 能量石
//两个相邻的石头i,j//先吃i后吃j获取的能量为Ei+Ej-Si*Lj//先吃j后吃i获取的能量为Ej+Ei-Sj*Li//所以当Li/Si>Lj>Sj是先吃i获取1的能量更多(贪心)#include<bits/stdc++.h>using namespace std;const int N = 110, M =11000;typedef pair<int,int> PII;typedef pair<int,pair<int,int>原创 2021-07-31 15:25:57 · 110 阅读 · 0 评论 -
AcWing 11. 背包问题求方案数
#include<bits/stdc++.h>using namespace std;const int N = 1100, MOD = 1e9+7;int v[N],w[N];int f[N],g[N];//f[i][j]表示体积恰好为j的最大价值,g[i][j]表示f[i][j]为最大价值的方案数int n,m;int main(){ cin>>n>>m; for(int i=1;i<=n;i++) scanf("%d%原创 2021-07-31 08:14:49 · 70 阅读 · 0 评论 -
AcWing 10. 有依赖的背包问题
#include<bits/stdc++.h>using namespace std;const int N = 110;int h[N],e[N],ne[N],idx;int v[N],w[N];int f[N][N];//以i为根节点,体积为j的最大价值int n,m;void add(int a,int b){ e[idx]=b; ne[idx]=h[a]; h[a]=idx++;}void dfs(int u){ for(int原创 2021-07-28 17:30:24 · 48 阅读 · 0 评论 -
AcWing 532. 货币系统
极大线性无关组#include<bits/stdc++.h>using namespace std;const int N = 110 , M = 30000;int T,n;int v[N];int f[M];int main(){ cin>>T; while(T--) { cin>>n; for(int i=1;i<=n;i++) scanf("%d",&v[i]原创 2021-07-23 16:10:54 · 78 阅读 · 0 评论 -
AcWing 12. 背包问题求具体方案
求具体方案可以使用反推,i从n遍历到1使得f[1][m]为最大价值。每件物品都有必选,必不选和可选三种情况,从1开始则当可选时为必选(字典序).m>=v[i]&&f[i][m]==f[i+1][m-v[i]]+w[i]//背包容量大于当前物品的重量(能选),且当初选择了该物品。#include<bits/stdc++.h>using namespace std;const int N = 1010;int n,m;int v[N],w[N],st[N];i原创 2021-07-07 15:45:29 · 47 阅读 · 0 评论 -
AcWing 1020. 潜水员
#include<bits/stdc++.h>using namespace std;const int N = 1010;int m,n,cnt;int a[N],b[N],c[N];int f[30][80];//从前k个气缸选择,氧气容量大于等于i,氮气容量大于等于j的最小重量int main(){cin>>m>>n>>cnt;for(int i=1;i<=cnt;i++)scanf("%d%d%d",&a[i],&am原创 2021-06-21 16:05:32 · 102 阅读 · 0 评论 -
AcWing 1022. 宠物小精灵之收服
m-1是因为皮卡丘血量要大于0,最多损血m-1第二问皮卡丘最大剩余体力dp[n][m - 1]:在所有小精灵中使用全部的精灵球且皮卡丘不挂的前提下所能捕捉小精灵的最大数量因为要是皮卡丘剩余体力最大,所以我们可以倒序遍历 m,即从可消耗最大体力来开始倒序遍历,那么当最多花费 m-1 体力时能捕捉最大小精灵的数量和使用 m 体力时能捕捉最大小精灵的数量 相同的话,即可证明皮卡丘可以省 1 点体力。以此类推,那么当全部遍历完成后,我们就可以得到皮卡丘可以节省的最大总体力数,再用皮卡丘的体力 - 可以节省的原创 2021-06-21 14:42:34 · 220 阅读 · 0 评论 -
AcWing 272. 最长公共上升子序列
O(n^3)时间复杂度f[i][j]:表示由第一个序列前i项和第二个序列前j项,并且以b[j]结尾的最长上升公共子序列状态分为公共子序列包含a[i]和不包含a[i]1.不包含a[i],则f[i][j]=f[i-1]j2.包含a[i],则分为倒数第二个数由第二个序列前j-1项或者空组成。(前提是要小于b[j]才能接上)f[i][j]=max(f[i][j],f[i][k])优化 O(n^2)时间复杂度当包含a[i],那a[i]是第一个序列的最后一项,b[j]是第二个序列的最后一项,则a[i..原创 2021-06-16 20:31:38 · 98 阅读 · 0 评论 -
AcWing 187. 导弹防御系统
#include<bits/stdc++.h>using namespace std;const int N = 55;int a[N],up[N],down[N];int n;int cnt;void dfs(int u,int uu,int dd){ //剪枝,并且只有比当前的cnt小,才能更新,换成n直接tle。。。 if(uu+dd>=cnt)return; //遍历完所有点后,就能求出最小的上升子序列和下降子序列之和 if(u=.原创 2021-06-16 16:30:49 · 60 阅读 · 0 评论 -
AcWing 1010. 拦截导弹
#include<bits/stdc++.h>using namespace std;const int N = 1010;int a[N],f[N],st[N];int n,cnt;int main(){ int x; while(cin>>x)a[1+n++]=x; //DP,最多能拦截的导弹数,最长不上升子序列 for(int i=1;i<=n;i++) { f[i]=1; for(i原创 2021-06-16 14:13:24 · 112 阅读 · 0 评论 -
AcWing 1012. 友好城市
思路:只要a城市位置在b城市的右边,且a城市的友好城市在b城市的友好城市的右边,则相连不会交叉。所以根据这个特性求北岸或南岸的LIS就行。b根据a的位置来记录,则a排序后不会影响求友好城市(对比a[i],b[i]排序后就不知道友好城市是谁了)#include<bits/stdc++.h>using namespace std;typedef pair<int,int> PII;const int N = 5050,M = 10010;int a[N],b[M],f[N];原创 2021-06-15 16:08:36 · 209 阅读 · 0 评论 -
AcWing 1027. 方格取数
思路:用思维数组记录两次走到的点,必须同时计算。(贪心算法计算两次dp的最大值是错的。)#include<bits/stdc++.h>using namespace std;const int N = 11;int f[N][N][N][N];//从(1,1)(1,1)走到(i1,j1)(i2,j2)取数总和的最大值int g[N][N];int n;int dx[]={0,-1},dy[]={-1,0};int main(){ cin>>n;原创 2021-05-27 00:02:00 · 64 阅读 · 0 评论 -
AcWing 1018. 最低通行费
#include<bits/stdc++.h>using namespace std;const int N = 110;int f[N][N],a[N][N];int n;int dx[]={0,0,1,-1},dy[]={1,-1,0,0};int main(){ cin>>n; for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) scanf("%d",原创 2021-05-26 21:30:22 · 66 阅读 · 0 评论 -
AcWing 1015. 摘花生
#include<bits/stdc++.h>using namespace std;const int N = 110;int f[N][N],g[N][N];int Q;int dx[]={0,1},dy[]={1,0};int main(){ cin>>Q; while(Q--) { memset(g,0,sizeof g); int n,m; scanf("%d%d",&n,&原创 2021-05-26 01:50:13 · 53 阅读 · 0 评论 -
AcWing 901. 滑雪
#include<bits/stdc++.h>using namespace std;typedef long long LL;const int N = 307;int f[N][N];int st[N][N];int a[N][N];int n,m;int dx[4]={-1,1,0,0};int dy[4]={0,0,1,-1};int dfs(int i,int j){ if(st[i][j]==-1) { st[i][j]=1原创 2021-05-15 22:21:36 · 73 阅读 · 0 评论 -
AcWing 285. 没有上司的舞会
//f[n][0]表示以u为根节点,但不选u的最大快乐指数//f[n][1]表示以u为根节点,并选择u的最大快乐指数//这题要从树的底部开始遍历而不是从1开始线性遍历,所以使用dfs求#include<bits/stdc++.h>using namespace std;const int N = 6007;int e[N],ne[N],h[N],idx;int f[N][N],ha[N];int n,root;bool is_root[N];void add(int.原创 2021-05-15 00:31:47 · 46 阅读 · 0 评论 -
AcWing 291. 蒙德里安的梦想
f[i][j],表示第i-1列已经摆好,j表示从i-1列伸向i列的状态的方案之和j 10010表示i-1列中第1行和第4行有小方块伸向第i列判断第i列是否合法 (1)i-2列伸向i-1列的方块与i-1列伸向i列的状态不冲突(2) 一列有连续的偶数的空格来放小方块#include<bitsdc++.h>using namespace std;typedef long long LL;const int N = 12, M = 1<<N;//M=2的N次方LL f[N原创 2021-05-13 20:12:17 · 50 阅读 · 0 评论 -
AcWing 900. 整数划分
整数划分转化为完全背包问题一个整数n可以被划分为多个正整数的方案数从1到n的物品选择使得体积恰好为n的方案书例:5=3+2 =》 体积为5的背包选择1个体积为3的物品,1个体积为2的物品二维//f[i][j]=f[i-1][j]+f[i][j-1];#include<bits/stdc++.h>using namespace std;const int MOD = 1e9+7;const int N = 1010;int f[N][N];int n;int mai.原创 2021-05-12 18:49:08 · 103 阅读 · 0 评论 -
AcWing 899. 编辑距离
#include<bits/stdc++.h>using namespace std;const int N = 1010;int f[N][N];int n,Q;char a[N][N];char b[N];int main(){ scanf("%d%d",&n,&Q); for(int i=1;i<=n;i++)scanf("%s",a[i]+1); for(int i=1;i<=10;i++)f[i][0]=f[0][原创 2021-05-10 23:17:45 · 66 阅读 · 0 评论 -
AcWing 902. 最短编辑距离
#include<bits/stdc++.h>using namespace std;const int N = 1010;int f[N][N];char a[N],b[N];int n,m;int main(){ scanf("%d%s",&n,a+1); scanf("%d%s",&m,b+1); //初始化 for(int i=1;i<=n;i++)f[i][0]=i;//b中没有数,只要删除i个字符使长度为i的a变原创 2021-05-10 22:52:20 · 52 阅读 · 0 评论 -
AcWing 91. 最短Hamilton路径
#include<bits/stdc++.h>using namespace std;const int N = 20, M = 1<<N;int a[N][N];int f[M][N];int n;int main(){ scanf("%d",&n); for(int i=0;i<n;i++) for(int j=0;j<n;j++) scanf("%d",&a[i][j]); //初始化 .原创 2021-05-13 23:50:25 · 48 阅读 · 0 评论