已此题为例:
http://acm.hdu.edu.cn/showproblem.php?pid=1864
原来的解法:
http://blog.youkuaiyun.com/gaotong2055/article/details/8579388
上面的解法中DFS太耗时。就算是使用典型的动态规划,耗费空间,数组开的太大,有很多浪费,有太多的无用循环,也会耗时(200ms左右)。
这里使用map存数中间值,节省了空间和时间。
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <map>
using namespace std;
double data[31];
int len,maxa;
double ans,q;
class OPT{
public:
int k;
double d;
OPT(int a,double b):k(a),d(b){}
OPT(){}
bool operator == (const OPT & o) const{
return k==o.k && d==o.d;
}
bool operator < (const OPT & o) const{
if(k == o.k)
return d < o.d;
else
return k < o.k;
}
};
map<OPT,double> opts; //存储中间结果
double dfs(int k,double remain)
{
OPT tmp(k, remain);
if(opts[tmp] )
return opts[tmp];
if(k>=len)
{
return 0;
}
if(remain >= data[k])
return opts[tmp] = max(dfs(k+1,remain-data[k])+data[k], dfs(k+1,remain));
else
return opts[tmp] = dfs(k+1,remain);
return 0;
}
int main()
{
int n,m;
char cc;
while(scanf("%lf %d",&q,&n)&&n!=0)
{
len=0;ans=-1;
for(int i=0;i<n;i++)
{
scanf("%d",&m);
double a=0,b=0,c=0,temp,sum=0;
int flag=1;
while(m--)
{
scanf(" %c:%lf",&cc,&temp);
if(cc=='A') a+=temp;
else if(cc=='B') b+=temp;
else if(cc=='C') c+=temp;
else flag=0;
sum+=temp;
}
if(flag&&sum<=1000&&a<=600&&b<=600&&c<=600)
data[len++]= sum ;
}
opts.clear();
ans = dfs(0,q);
printf("%.2f\n",ans);
}
}