2021-08-01 acwing算法基础课 动态规划

AcWing 2. 01背包问题

1.题意:
2.题解:
3.ac代码:
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <iostream>
const int N=1e6+10;
using namespace std;
int n,m;
int f[N];
int v[N],w[N];
int main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		cin>>v[i]>>w[i];
	}
	for(int i=1;i<=n;i++)
	for(int j=m;j>=v[i];j--){
		f[j]=max(f[j],f[j-v[i]]+w[i]);
	}
	cout<<f[m]<<endl;
}

AcWing 3. 完全背包问题

1.题意:
2.题解:
3.ac代码:
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <iostream>
const int N=1e6+10;
using namespace std;
int n,m;
int f[N];
int v[N],w[N];
int main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		cin>> v[i]>>w[i];
	}
	for(int i=1;i<=n;i++)
	for(int j=v[i];j<=m;j++){
		f[j]=max(f[j],f[j-v[i]]+w[i]);
	}
	cout<<f[m]<<endl;
}

AcWing 4. 多重背包问题

1.题意:
2.题解:
3.ac代码:
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <iostream>
const int N=1e6+10;
using namespace std;
int n,m;
int f[200][200];
int v[N],w[N],s[N];
int main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		cin>> v[i]>>w[i]>>s[i];
	}
	for(int i=1;i<=n;i++){
		for(int j=0;j<=m;j++){
			for(int k=0;k<=s[i]&&k*v[i]<=j;k++){
				f[i][j]=max(f[i][j],f[i-1][j-k*v[i]]+k*w[i]);//!!是f[i][j] 
			}
		}
	}
	cout<<f[n][m]<<endl;
}

AcWing 5. 多重背包问题 II

1.题意:
2.题解:
3.ac代码:
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <iostream>
const int N=1e6+10;
using namespace std;
int n,m;
int f[N];
int v[N],w[N];
int main(){
	cin>>n>>m;
	int cnt=0;
	for(int i=1;i<=n;i++){
		int a,b,s;
		cin>>a>>b>>s;
	
		int k=1;
		
		while(k<=s){
			cnt++;
			v[cnt]=k*a;
			w[cnt]=k*b;
			s-=k;
			k*=2;
		}
		if(s>0){
			cnt++;
			v[cnt]=s*a;
			w[cnt]=s*b;
		}
		
	}
	for(int i=1;i<=cnt;i++){
		for(int j=m;j>=v[i];j--){
			f[j]=max(f[j],f[j-v[i]]+w[i]);
		}
	}
	cout<<f[m]<<endl;
}

AcWing 9. 分组背包问题

1.题意:
2.题解:
3.ac代码:
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <iostream>
const int N=1e6+10;
using namespace std;
int s[N],f[N],v[200][200],w[200][200];
int main(){
    int n,m;
    cin>>n>>m;
    int t=1;
    for(int i=1;i<=n;i++){
        cin>>s[i];
        
        for(int j=0;j<s[i];j++){
            cin>>v[i][j]>>w[i][j];
        }
   
    }
    for(int i=1;i<=n;i++){
        for(int j=m;j>=0;j--){
            for(int k=0;k<s[i];k++){
                if(j>=v[i][k]){
                    f[j]=max(f[j],f[j-v[i][k]]+w[i][k]);
                }
            }
        }
    }
    cout<<f[m]<<endl;
}

AcWing 898. 数字三角形

1.题意:
2.题解:
3.ac代码:
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <iostream>
const int N=1e6+10;
using namespace std;
int n,m;
int a[600][600];
int dp[600][600];

int main(){
	int n;
	cin>>n;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=i;j++){
			cin>>a[i][j];
		}
	}
//	for(int i=0;i<=n;i++){
//		for(int j=0;j<=n;j++){
//			dp[i][j]=-Inf;
//		}
//	}
	for(int i=n-1;i>=1;i--){
		for(int j=1;j<=i;j++){
			a[i][j]=a[i][j]+max(a[i+1][j],a[i+1][j+1]);
		}
	}
	cout<<a[1][1]<<endl;
}

AcWing 895. 最长上升子序列

1.题意:
2.题解:
3.ac代码:
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <iostream>
const int N=1e6+10;
using namespace std;
int n,m;
int a[N];
int f[N];
//const Inf=0x3f3f3f3f;
int main(){
	int n;
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	for(int i=1;i<=n;i++){
		f[i]=1;
		for(int j=1;j<i;j++){
			if(a[j]<a[i])
			f[i]=max(f[j]+1,f[i]);
		}
	}
	int res=0;
	for(int i=1;i<=n;i++){
		res=max(res,f[i]);
	}
	cout<<res<<endl;
}

AcWing 896. 最长上升子序列 II

1.题意:
2.题解:

注:l和r len初始值都为0
二分,若l=mid,那么求mid时要+1

3.ac代码:
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <iostream>
const int N=1e6+10;
const int INF=0x3f3f3f3f;
int a[N],q[N];
using namespace std;
int main(){
	int n;
	cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i];
	q[0]=-INF; 
	int len=0;
	for(int i=1;i<=n;i++){
		int l=0;
		int r=len;
		while(l<r){
			int mid=l+r+1>>1;
			if(q[mid]<a[i]) l=mid;
			else r=mid-1;
		}
		len=max(len,r+1);
		q[r+1]=a[i];
	}
	cout<<len<<endl;
}

AcWing 897. 最长公共子序列

1.题意:
2.题解:
3.ac代码:
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <iostream>
const int N=1e6+10;
using namespace std;
int n,m;
char a[N],b[N];
int f[N];
int dp[2000][2000];
//const Inf=0x3f3f3f3f;
int main(){
//	int n;
	cin>>n>>m;
	scanf("%s%s",a+1,b+1);
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			if(a[i]==b[j]){
				dp[i][j]=dp[i-1][j-1]+1;
			}else {
				dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
			}
		}
	}
	cout<<dp[n][m]<<endl;
}

AcWing 902. 最短编辑距离

1.题意:
2.题解:
3.ac代码:
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <iostream>
using namespace std;
const int N=1e6+10;
const int INF=0x3f3f3f3f;
char a[N],b[N];
int f[2010][2010];
int main(){
	int n,m;
	cin>>n;
	scanf("%s",a+1);
	cin>>m;
	scanf("%s",b+1);
	for(int i=0;i<=n;i++) f[i][0]=i;
	for(int i=0;i<=m;i++) f[0][i]=i;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			f[i][j]=min(f[i][j-1],f[i-1][j])+1;
			f[i][j]=min(f[i][j],f[i-1][j-1]+(a[i]!=b[j]));
			
		}
	}
	cout<<f[n][m];
}

AcWing 899. 编辑距离

1.题意:
2.题解:
3.ac代码:
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <iostream>
using namespace std;
const int N=1e6+10;
const int INF=0x3f3f3f3f;
char a[N],b[N];
int f[2010][2010];
int cmp(char a[],char b[]){
	int la=strlen(a+1),lb=strlen(b+1);
	for(int i=0;i<=la;i++) f[i][0]=i;
	for(int j=0;j<=lb;j++) f[0][j]=j;
	for(int i=1;i<=la;i++){
		for(int j=1;j<=lb;j++){
			f[i][j]=min(f[i-1][j],f[i][j-1])+1;
			f[i][j]=min(f[i][j],f[i-1][j-1]+(a[i]!=b[j]));
		}
	}
	return f[la][lb];
}
char str[N][12];
int main(){
	int n,m;
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		scanf("%s",str[i]+1);
	}
	for(int i=1;i<=m;i++){
		char s[12];
		scanf("%s",s+1);
		int t;
		int res=0;
		cin>>t;
		for(int j=1;j<=n;j++){
			int ans=cmp(str[j],s);
			if(ans<=t) res++;
		}
		cout<<res<<endl;
	}

}

AcWing 282. 石子合并

1.题意:
2.题解:
3.ac代码:
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <iostream>
const int N=1e6+10;
using namespace std;
int n,m;
int a[N],s[N];
int f[N];
int dp[2000][2000];
const int INF=0x3f3f3f3f;
int main(){
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        s[i]=s[i-1]+a[i];
    }
    for(int len=2;len<=n;len++){
        for(int i=1;i<=n-len+1;i++){
            int j=i+len-1;
            dp[i][j]=INF;
            for(int k=i;k<j;k++){
                dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]+s[j]-s[i-1]);
            }
        }
    }
    cout<<dp[1][n]<<endl;

}

AcWing 900. 整数划分

1.题意:
2.题解:
3.ac代码:
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <iostream>
using namespace std;
const int N=1e6+10;
const int INF=0x3f3f3f3f;
const int mod=1e9+7;
char a[N],b[N];
int f[N];
int n;
int main(){
	cin>>n;
	f[0]=1;
	for(int i=1;i<=n;i++){
		for(int j=i;j<=n;j++){
			f[j]=(f[j]+f[j-i])%mod;
		}
	}
	cout<<f[n]<<endl;
}

AcWing 338. 计数问题

1.题意:
2.题解:

分类讨论!!!

3.ac代码:
#include<bits/stdc++.h>
#include <iostream>
#include <algorithm>
#include <cmath>
#include<set>
#include<vector> 
#include<map>
using namespace std;
typedef long long ll;
const int N=1e6+10;
int get(vector<int> num,int l,int r){
	int res=0;
	for(int i=l;i>=r;i--){
		res=res*10+num[i];
	}
	return res;
}
int pow10(int n){
	int res=1;
	while(n){
		res=res*10;
		n--;
	}
	return res;
}
int count(int n,int x){
	if(!n) return 0;
	vector<int> num;
	while(n){
		num.push_back(n%10);
		n=n/10;
	}
	n=num.size();
	int res=0;
	for(int i=n-1-!x;i>=0;i--){
		if(i<n-1){
			res+=get(num,n-1,i+1)*pow10(i);
			if(!x) res-=pow10(i);
			
		}
		if(num[i]==x) res+=get(num,i-1,0)+1;
		else if(num[i]>x) res+=pow10(i);
	}
	return res;
}
int main(){
	int a,b;
	while(cin>>a>>b,a||b){
		if(a>b) swap(a,b);
		for(int i=0;i<10;i++){
			cout<<count(b,i)-count(a-1,i)<<" ";
		
		}
			cout<<endl;
	}
}

AcWing 291. 蒙德里安的梦想

1.题意:
2.题解:

所有方案数=所有合法的横方格放置方案数
f[i][j]代表第i列是否有1x2方格中第二个方格的情况
f[i][j]=f[i-1][k]和 ,k=0,k=1<<n,前一个方案的情况导致了下一个方案
合法:
1.前一列和当前列不能有重叠的1,因为f[i][j]代表从前一列开始到第i列结束的1x2方格,在i-1列,她是0,到第i列给他安上了1x2的方格,
2.前一列剩余的连续空格必须是偶数个,(这个剩余指的是+到该列为止的1x2方格),所以用st[i|j],i和j中所有1的并才是前一列真正剩余的空格情况
所以求时分两个方面,先找出所有符合2的情况用st存,st总共有1<<n种情况,
遍历两列各有1<<n种情况,看满足1吗,即i&j ==0,再看满足2吗即st[i|j],若满足,则将当前的j(代表前一列的情况)存入state【i】
从1到m遍历,对每一个j(0~1<<n)求其方案数和
f[0][0]代表第0列没有从前面列伸出来的方块,此时没有横方块,也是一种方案
f【m][0]代表实际上的m+1列即前m列都已合法填过且符合要求,不会有伸到第m+1的方格,显然是答案。

3.ac代码:
#include<bits/stdc++.h>
#include<vector>
using namespace std;
typedef long long ll;
const int N=12;const int M=1<<N;
ll f[N][M];
vector<int> state[M];
bool st[M];
int main(){
    int n,m;
    while(cin>>n>>m,n||m){
        for(int i=0;i<1<<n;i++){
            bool iv=true;
            int cnt=0;
            for(int j=0;j<n;j++){
                if((i>>j)&1){
                    if(cnt&1){
                        iv=false;
                        break;
                    }
                    cnt=0;
                }else{
                    cnt++;
                }
            }
            if(cnt&1) iv=false;
            st[i]=iv;
        }
        for(int i=0;i<1<<n;i++){
            state[i].clear();
            for(int j=0;j<1<<n;j++){
                if((i&j)==0&&st[i|j]){
                    state[i].push_back(j);
                }
            }
        }
        memset(f,0,sizeof f);
        f[0][0]=1;
        for(int i=1;i<=m;i++){
            for(int j=0;j<1<<n;j++){
                for(auto k:state[j]){
                    f[i][j]+=f[i-1][k];
                }
            }
        }
        cout<<f[m][0]<<endl;
    }
}

AcWing 91. 最短Hamilton路径

1.题意:
2.题解:

注意±的优先级高于位运算,位运算优先级高于&

3.ac代码:
#include<bits/stdc++.h>
#include <iostream>
#include <algorithm>
#include <cmath>
#include<set>
#include<vector> 
#include<map>
using namespace std;
typedef long long ll;
int n;
const int N=21;
int f[1<<N][N];
int w[N][N];
int main(){
    cin>>n;
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            cin>>w[i][j];
        }
    }
    memset(f,0x3f,sizeof f);
    f[1][0]=0;
     
    for(int i=0;i<1<<n;i++){
        for(int j=0;j<n;j++){
            if(i>>j&1){
                for(int k=0;k<n;k++){
                    if((i>>k) &1){
                        f[i][j]=min(f[i][j],f[i-(1<<j)][k]+w[k][j]);
                    }
                }
            }
        }
    }
    cout<<f[(1<<n)-1][n-1]<<endl;
}

AcWing 285. 没有上司的舞会

1.题意:
2.题解:
3.ac代码:
#include<bits/stdc++.h>
#include <iostream>
#include <algorithm>
#include <cmath>
#include<set>
#include<vector> 
#include<map>
using namespace std;
typedef long long ll;
const int N=1e6+10;
int h[N],e[N],ne[N],idx;
int happy[N];
bool fa[N];
int f[N][2];
void add(int a,int b){
	e[idx]=b;ne[idx]=h[a];h[a]=idx++;
}
void dfs(int u){
	f[u][1]=happy[u];
	for(int i=h[u];i!=-1;i=ne[i]){
		int j=e[i];
		dfs(j);
		f[u][0]+=max(f[j][1],f[j][0]);
		f[u][1]+=f[j][0];
	}
}
int isfa(int n){
	for(int i=1;i<=n;i++){
		if(fa[i]==false)
		   return i;
	}
}
int main(){
	int n;
	cin>>n;
	for(int i=1;i<=n;i++) cin>>happy[i];
	memset(h,-1,sizeof h);
	for(int i=1;i<n;i++){
		int a,b;
		cin>>a>>b;
		add(b,a);
		fa[a]=true;
	}
	int root=isfa(n);
	dfs(root);
	int ans=max(f[root][0],f[root][1]);
	cout<<ans<<endl;
}

AcWing 901. 滑雪

1.题意:
2.题解:
3.ac代码:
#include<bits/stdc++.h>
#include <iostream>
#include <algorithm>
#include <cmath>
#include<set>
#include<vector> 
#include<map>
using namespace std;
typedef long long ll;
const int N=1e6+10;
int n;
int dx[4]={-1,0,1,0};
int dy[4]={0,1,0,-1};
int f[301][401];
int h[301][301];
int r,c;
int dp(int x,int y){
    int &v=f[x][y];
    if(v!=-1){
        return v;
    }
    v=1;
    for(int i=0;i<4;i++){
        int a=x+dx[i];
        int b=y+dy[i];
        if(a>=1&&a<=r&&b>=1&&b<=c&&h[x][y]>h[a][b]){
            v=max(v,dp(a,b)+1);
        }
    }
    return v;
}
int main(){
    cin>>r>>c;
    for(int i=1;i<=r;i++){
        for(int j=1;j<=c;j++){
            cin>>h[i][j];
        }
    }
    memset(f,-1,sizeof f);
    int res=0;
    for(int i=1;i<=r;i++){
        for(int j=1;j<=c;j++){
            res=max(res,dp(i,j));
        }
    }
    cout<<res<<endl;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: acwing算法基础课是一门针对算法学习的在线课程,在这门课程中,学生可以系统地学习和掌握算法基础知识,提高编程水平。为了方便学生学习,acwing提供了网盘服务。 acwing算法基础课网盘是一个用于存储课程资源的平台。通过这个网盘,学生可以下载课程讲义、代码模板以及补充材料等。这些资源都经过精心整理,供学生们参考和学习。 网盘中的资源是按照课程章节进行分类的,学生可以根据自己的学习需要,选择性地下载所需的资料。同时,网盘还提供了搜索功能,方便学生快速定位和获取所需资料。 acwing算法基础课网盘的使用对于学生们的学习非常有帮助。通过下载和学习这些资源,学生们可以更好地理解课程内容,加深对算法的理解。此外,学生们还可以通过研究代码模板,学习优秀的编程思想和技巧,提高自己的编程能力。 总之,acwing算法基础课网盘是一项非常便利和实用的服务,为学生们提供了更加全面和深入的学习资源,帮助他们更好地掌握和运用算法知识。 ### 回答2: acwing算法基础课是一门优质的算法学习资源,其中的课程内容丰富多样,涵盖了算法基础知识、数据结构、动态规划、图论等等。很多学习者都认为这门课程对他们的算法学习有很大的帮助。 网盘是指以网络为媒介,提供文件存储和下载服务的云存储平台。acwing算法基础课也提供了网盘服务,方便学习者下载课程资料并进行学习。 通过acwing算法基础课网盘,学习者可以方便地获取到课程的各种学习资料,包括讲义、习题集、代码示例等。这些资料可以帮助学习者更好地理解和掌握课程的内容。此外,网盘还提供了上传和分享功能,学习者可以将自己的学习心得、代码等资料分享给其他学习者,促进学习者之间的互相学习和交流。 acwing算法基础课网盘的优点不仅仅是方便快捷的下载和分享功能,还包括安全可靠的存储环境。学习者可以放心地将自己的学习资料上传到网盘进行备份,减少数据丢失的风险。同时,网盘还提供了多种存储空间容量的选择,满足学习者不同的需求。 总的来说,acwing算法基础课网盘为学习者提供了方便、安全和多样化的学习资源下载和分享服务,为学习者的算法学习和进步提供了有力的支持。如果你对算法感兴趣,我推荐你去尝试一下这门精彩的课程!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值