本周训练让我切身体会了算法的魅力和学习需求,还有很多的算法需要我去掌握。
这是其中我印象较为深刻的一道题
P1048 [NOIP2005 普及组] 采药
我的理解是,将草药一个一个放入背包中,如果放入时超过了限重,则最佳方案为不放入,即dp[i-1][j]=dp[i][j];反之则判断放入的方案和不放入的方案哪个价值更高。
应该是这样吧awa。
AC代码如下
#include <bits/stdc++.h>
using namespace std;
int main(){
int t,m,a[1010],b[1010],c[1010][1010];
cin>>t>>m;
for(int i=1; i<=m; i++){
cin>>a[i]>>b[i];
}
for(int i=1; i<=m; i++){
for(int j=1; j<=t; j++){
if(a[i]>j)
c[i][j]=c[i-1][j];
else
c[i][j]=max(c[i-1][j],c[i-1][j-a[i]]+b[i]);
}
}
cout<<c[m][t];
return 0;
}
说实话,这还是我第一次真正学习背包问题。在经过基础的学习之后,我对背包问题也是有了一个大致的认知。
不久后,我再次遇到了这类问题。
P8742 [蓝桥杯2021 省 AB] 砝码称重
这道题要思考的更多,多个砝码可以相加相减,但核心依然是背包问题。
先从一个砝码入手,再开始加减,就是把加号换成减号,并注意绝对值就行了。
AC代码如下
#include<bits/stdc++.h>
using namespace std;
int n,a[110],sum,ans=0,d[110][100010];
int main() {
cin>>n;
for(int i=1; i<=n; i++){
cin>>a[i];
sum+=a[i];
}
for(int i=1; i<=n; i++){
for(int j=sum;j ;j--){
if(j==a[i])
d[i][j]=1;
else if(d[i-1][j]==1)
d[i][j]=1;
else if(d[i-1][j+a[i]]==1)
d[i][j]=1;
else if(d[i-1][abs(j-a[i])]==1)
d[i][j]=1;
}
}
for(int i=1; i<=sum; i++){
if(d[n][i])
ans++;
}
printf("%d",ans);
return 0;
}
这道题的难度明显比上一题高,我也是费了九牛二虎之力才做出这道题。虽然过程较为艰难,但解出题的感觉确实很妙啊。
看着上面那些大佬解题如喝水,我是既震惊又羡慕,看来还得多多练习啊。
我目前也有许多不足,如面对较大的数据无法处理导致RE,比赛状态进入较慢,算法储量过小等问题都成为了我目前急需解决的问题,希望在接下来的学习中能更上一层楼吧。