DSA二组讲题2021.11.11
P1024 一元三次方程求解
#include <bits/stdc++.h>
using namespace std;
double a,b,c,d;
double fc(double x)
{
return a*x*x*x+b*x*x+c*x+d;
}
int main()
{
double l,r,m,x1,x2;
int s=0; //s用来计数
scanf("%lf%lf%lf%lf", &a, &b, &c, &d); //输入
for (int i = -100; i < 100; i++)
{
l=i;
r=i+1;
x1=fc(l);
x2=fc(r);
if(!x1)
{
printf("%.2lf ",l);
s++;
} //判断左端点,是零点直接输出
//不能判断右端点,会重复,因为右端点是左端点加一,下一次循环就会重复
if(x1*x2<0) //区间内有根。
{
while(r-l>=0.001) //二分控制精度。
{
m=(l+r)/2;
if(fc(m)*fc(r)<=0)
l=m;
else
r=m; //计算中点处函数值缩小区间。
}
printf("%.2lf ",l);
//这里输出左右端点都是一样的,输出中间值m也可以
s++;
}
if (s==3)
break;
//找到三个就退出大概会省一点时间
}
return 0;
}
#include <iostream>
#include <cstdio>
using namespace std;
int main()
{
double a,b,c,d;
scanf("%lf%lf%lf%lf",&a,&b,&c,&d);
for(double i=-100;i<=100;i+=0.001)
{
double j=i+0.001;
double y1=a*i*i*i+b*i*i+c*i+d;
double y2=a*j*j*j+b*j*j+c*j+d;
if(y1>=0&&y2<=0||y1<=0&&y2>=0)
{
double x=(i+j)/2;
printf("%.2lf ",x);
}
}
}
P1048 采药
01背包
1.不选,然后去考虑下一个
2.选,背包容量减掉那个重量,总值加上那个价值。
| 1 | 2 | 3 | 4 | |
|---|---|---|---|---|
| 吉他 占一格 1500元 | 1500 | 1500 | 1500 | 1500 |
| 音响 占四格 3000元 | 1500 | 1500 | 1500 | 3000 |
| 笔记本电脑 占三格 2000元 | 1500 | 1500 | 2000 | 3500 |
#include <bits/stdc++.h>
using namespace std;
int w[105],val[105];
int dp[105][1005];
int main()
{
int t,m,res=-1;
scanf("%d%d",&t,&m);
for(int i=1;i<=m;i++)
{
scanf("%d%d",&w[i],&val[i]);
}
for(int i=1;i<=m;i++) //i理解为物品,j理解为空间
for(int j=0;j<=t;j++)
{
dp[i][j]=dp[i-1][j];//这就是直接什么都不选,所以就是上一行的数据
if(j>=w[i])//位置可以装下的话
{
dp[i][j]=max(dp[i-1][j-w[i]]+val[i],dp[i-1][j]);//比较这次不拿和拿了再加上价值哪个大
} 都是用i-1行的数据
}
printf("%d",dp[m][t]);//输出最后一行最后一列就是考虑了所有物品、最大空间的最大价值
return 0;
}
#include <bits/stdc++.h>
using namespace std;
int w[105], val[105];
int dp[1005];//只存储价值
int main()
{
int t,m,res=-1;
scanf("%d%d",&t,&m);
for(int i=1;i<=m;i++)
{
scanf("%d%d",&w[i],&val[i]);
}
for(int i=1;i<=m;i++) //还是从第一个物品开始循环
{
for(int j=t;j>=0;j--) //从最大容量开始看,防止前面的被覆盖,使得后面的出错
{
if(j>=w[i])
{
dp[j]=max(dp[j-w[i]]+val[i], dp[j]);
}
}
}
printf("%d",dp[t]);
return 0;
}
P1616 疯狂的采药
本题数据范围较大,需要开long long
状态转移方程推导
完全背包的状态转移方程:dp(i,j)=max(dp(i-1,j),dp(i,j-v)+val[i]) 这里第二项就不是i-1了,是i了,也正是因为是i,所以一维优化时正着来
就是要么是左边的,要么是上方的
完全背包的一维优化
dp[j]=max(dp[j],dp[j-v]+w)
AC代码
#include <bits/stdc++.h>
using namespace std;
const int maxm = 10010, maxt = 10000010;
long long v[maxm], t[maxm], f[maxt];//开long long!
int main()
{
int T , m;
cin >> T >> m;
for(int i = 1;i <= m ;i ++)
cin >> t[i] >> v[i];
for(int i = 1;i <= m;i ++)
for(int j = 0;j <= T;j++)/*完全背包必须正着来,需要覆盖
0-1背包必须反着来,不能被覆盖*/
if(j>=t[i])
f[j] = max(f[j],f[j - t[i]] + v[i]);
cout << f[T];
}
P1064 金明的预算方案
01背包
1.不选,然后去考虑下一个
2.选,背包容量减掉那个重量,总值加上那个价值。
本题选择情况
1.不选,然后去考虑下一个
2.选且只选这个主件
3.选这个主件,并且选附件1
4.选这个主件,并且选附件2
5.选这个主件,并且选附件1和附件2.
这五种情况就会带来四次的max函数比较
#include <bits/stdc++.h>
#define maxn 32005
using namespace std;
int n,m;
int v,p,q;
int main_item_w[maxn];//主物件的价格
int main_item_c[maxn];//主物件的重要度
int annex_item_w[maxn][3];//附件的价格
int annex_item_c[maxn][3];//附件的重要度
int f[maxn];
int main(){
cin >> n >> m;//总钱数n,可以购买的主物件m件
for (int i=1;i<=m;i++){
cin >> v >> p >> q;//v,p,q分别代表价格,重要度,它属于的主物件,q如果等于0,则自己就是主物件
if (!q){//自己是主物件
main_item_w[i] = v;
main_item_c[i] = v * p;//本题目中最终需要的价值 = 重要度 * 价格
}
else{//自己不是主物件
annex_item_w[q][0]++;//这里存储的是自己是第几个附件
annex_item_w[q][annex_item_w[q][0]] = v;//属于主物件q的第annex_item_w[q][0]个附件的价格
annex_item_c[q][annex_item_w[q][0]] = v * p;//属于主物件q的第annex_item_w[q][0]个附件的价值
}
}
for (int i=1;i<=m;i++)
for (int j=n;main_item_w[i]!=0 && j>=main_item_w[i];j--){
//j=n倒着来,循环终止条件为主物品不等于0且j不小于本件主物品的价格
f[j] = max(f[j],f[j-main_item_w[i]]+main_item_c[i]);//不选附件
if (j >= main_item_w[i] + annex_item_w[i][1])//选择附件1
f[j] = max(f[j],f[ j - main_item_w[i] - annex_item_w[i][1] ] + main_item_c[i] + annex_item_c[i][1]);
if (j >= main_item_w[i] + annex_item_w[i][2])//选择附件2
f[j] = max(f[j],f[ j - main_item_w[i] - annex_item_w[i][2] ] + main_item_c[i] + annex_item_c[i][2]);
if (j >= main_item_w[i] + annex_item_w[i][1] + annex_item_w[i][2])//附件1和附件2都选择
f[j] = max(f[j],f[ j - main_item_w[i] - annex_item_w[i][1] - annex_item_w[i][2] ] + main_item_c[i] + annex_item_c[i][1] + annex_item_c[i][2]);
}
cout << f[n] << endl;//输出最终结果
return 0;
}

浙公网安备 33010602011771号