P1802-DP【橙】
1.又是一道因为写了异常剪枝而调了好久的题,以后再也不写异常剪枝了,异常情况压根不该出现,所以针对出现的异常情况进行补救的异常剪枝是一种很容易出错的行为,做为两手准备也就罢了,但第一次写成的代码必须能在没有异常剪枝的情况下算出正确结果才行!
2.还提出了一个专门针对记搜的编码规范:编写记忆化搜索的时候不要使用除了DP以外的全局变量,要用外界常量就用一个一直传着的常量引用如const int &
(注意,指向常量的指针写作int * const p,而常量引用写作 const int & p,但两者是同一个东西,都是不允许修改指向对象的,注意,指向常量的指针和常量引用都并不是只能指向常量,而是不能修改指向的量,换句话说可以指向变量,只是用指针和引用来表示指向的变量的时候那个变量会表现成一个常量的样子,但并不是新创建了一个与之相等的常量来被指)
3.同时,十年OI一场空,不开ll见祖宗啊QAQ
而且很多时候把int改成ll会忘了改返回值类型等较小的地方,导致错误,所以不如#define int long long,signed main,真香
4.然后还是WA了,因为忽略了还有重量为0的商品,即不用嗑药也能打过的菜鸡,所以边界应该是“if(remain<0||cdP==0)return DP[remain][cdP]=0;//边界剪枝”而不是“if(remain==0||cdP==0)return DP[remain][cdP]=0;//边界剪枝”
Code
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <map>
#include <vector>
#include <queue>
#include <cmath>
using namespace std;
#define int long long
int DP[1005][1005];
//remian is the remain count of drug ,and cdP is the considered_person_number
//the return value is the answer of I have these drugs and these persons
//标准编码规范:编写记忆化搜索的时候不要使用除了DP以外的全局变量,要用外界常量就用一个一直传着的常量引用如const int &
int dfs(int remain,int cdP, const int * const w,const int * const u)
{
if(DP[remain][cdP]!=-1)return DP[remain][cdP];//记忆化剪枝
if(remain<0||cdP==0)return DP[remain][cdP]=0;//边界剪枝
int DFS=0;//总种数就加、最优解就取MAX(或MIN)
if(remain-u[cdP]>=0)DFS=max(DFS,dfs(remain-u[cdP],cdP-1,w,u)+w[cdP]);
DFS=max(DFS,dfs(remain,cdP-1,w,u));
return DP[remain][cdP]=DFS;
}
signed main()
{
int x,n,ans=0,l[1005],w[1005],u[1005];
cin>>n>>x;
memset(DP,-1,sizeof(DP));
for(int i=1;i<=n;i++)
cin>>l[i]>>w[i]>>u[i];
for(int i=1;i<=n;i++)w[i]-=l[i],ans+=l[i];
cout<<5*(ans+dfs(x,n,w,u))<<endl;
return 0;
}