今天学习内容:1.dp背包问题
(1)01背包:状态方程(二维):
dp[i][j]=max(dp[i-1][j],dp[i-1][j-m[i]]+v[i]) (j>=m[i])
方程中dp[i-1]可删去简化变成一维,dp[j]=max(dp[j],dp[j-m[i]]+v[i])。
注意:二维方程需要if判断条件,但是一维不需要,
(2)完全背包:就是拿物品次数变成无数次。
状态方程:dp[i][j]=max(dp[i-1][j],dp[i-1][j-k*m[i]]+k *v[i]) (0<=k * m[i]<=j)
(3)多重背包:有限次的拿物品。
状态方程:dp[i][v] = max{dp[i - 1][v - k * c[i]] + w[i] | 0 <=k <= n[i]}
附上今天刷的一道题 HDU - 1171
题目大意,有n个价值物品,每个价值物品可能有1个以上,要求平均分成两份,第一份大于等于第二份。
这道题两种方法:第一种,均分01背包,第二种方法多重背包。
我用的均分01背包。
大概思路:所有价值总和除2就是一分最小价值(第二份)
直接01背包完成
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int t,m[255555],number,num,sum,dp[255555];
int max(int x,int y){
if(x>y)
return x;
else
return y;
}
int main(){
while(~scanf("%d",&t)){
if(t<0)
break;
memset(m,0,sizeof(m));
memset(dp,0,sizeof(dp));
sum=0;
int k=1;
for(int i=1;i<=t;i++){
scanf("%d%d",&num,&number);
m[k]=num;
sum+=m[k++]*number;
for(int j=2;j<=number;j++)
m[k++]=num;
}
int n=sum/2;
for(int j=1;j<k;j++)
for(int i=0;i<=n;i++)
if(i>=m[j])
dp[i]=max(dp[i],dp[i-m[j]]+m[j]);
printf("%d %d\n",sum-dp[n],dp[n]);
}
return 0;
}
有点坑的就是数组范围是5050100。。我开的5005一直超时。。。很神奇居然不是runtime。
今天还学习了搜索,DBFS这个就是2个BFS双向比一个BFS时间快,空间小。
还有看懂了A算法,实现就是有点难,用它解决八数码问题。
A算法灵魂 F(x)=H(x)+G(x)
H(x)就是估算距离。有很多估算思想我就会一个M开头的
G(x)就是自己设定距离一般一个方块10,对角线14(约等于),数值看自己爱好。
每次找路是找F(x)最小值,所以它的缺点就很明显如果有多个F(x)最小值寻路,那么他不一定找到的是最短路。
然后A=算法升级版就是IDA算法,就是限制层数的A算法,看博客说极其优化,简单的公式。。。。。