模仿自:http://blog.csdn.net/squee_spoon/article/details/38014425#
(下面说的都是假的)
自己明明看过别人的代码的,结果写的代码还是TLE,因为我是对于每一个邮票集合都求,,这样的话可能会出现很大的情况。。因为10*200*
然后别人的题解是根据能不能到达某个价值来求。。。而且有一个更坑的是,我把别人的代码的int数组改为bool数组就会超时。。。(我明明记得又一次如果用的在函数中如果用的是bool函数反而会快,用int返回的函数反而超时。。。
(上面说的都是假的。。。)
其实我的TLE 的原因和改他的TLE d原因只是因为 d!=-1表示没有计算过,其他表示计算过,所以就记忆化。。
这是记忆化的做法:
我的
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<string>
#include<cstring>
#include<iomanip>
#include<iostream>
#include<stack>
#include<cmath>
#include<map>
#include<vector>
#define ll long long
#define inf 0x3f3f3f3f
#define INF 1000000000
#define bug1 cout<<"bug1"<<endl;
#define bug2 cout<<"bug2"<<endl;
#define bug3 cout<<"bug3"<<endl;
using namespace std;
int s,set;
int stamp[12][12];
int d[1110][12];
int dp(int kind,int n,int s){
if(d[n][s]!=-1)return d[n][s];
if(!n)return d[n][s]=1;
if(!s)return d[n][s]=0;
for(int i=1;i<=stamp[kind][0];++i){
if(n-stamp[kind][i]>=0)
if(dp(kind,n-stamp[kind][i],s-1))return d[n][s]=1;
}
return d[n][s]=0;
}
int maxans[12];
int ansid,ans;
void getans(int st,int s){
memset(d,-1,sizeof(d));
for(int i=1;i<inf;++i){
if(!dp(st,i,s)){maxans[st]=i-1;return;}
}
}
int solve(){
for(int i=1;i<=set;++i){getans(i,s);}
for(int i=1;i<=set;++i){
if(ans<maxans[i]){
ans=maxans[i];
ansid=i;
}
else if(ans==maxans[i]){
if(stamp[ansid][0]<stamp[i][0]){
ans=maxans[i];
ansid=i;
}
else if(stamp[ansid][0]==stamp[i][0]){
for(int j=stamp[ansid][0];j>=1;j--){
if(stamp[ansid][j]<stamp[i][j]){
ans=maxans[i];
ansid=i;
break;
}
}
}
}
}
return ans;
}
int main(){
while(~scanf("%d",&s)&&s){
scanf("%d",&set);
for(int i=1;i<=set;++i){
scanf("%d",&stamp[i][0]);
for(int j=1;j<=stamp[i][0];++j){
scanf("%d",&stamp[i][j]);
}
}
printf("max coverage = %4d:",solve());
}
}
还有一个用完全背包的做法。。感觉非常好。。
转自http://www.cnblogs.com/zyb993963526/p/6380042.html
#include<iostream>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 25;
const int INF = 0x3f3f3f3f;
int s, n, m;
int a[maxn];
int dp[1005];
int ans[25];
int main()
{
//freopen("D:\\txt.txt", "r", stdin);
while (cin >> s && s)
{
int best = 0; //最大连续邮资
int Max=INF; //最大邮票的值
int number = INF; //邮票数量
cin >> n;
for (int i = 0; i < n; i++)
{
cin >> a[0];
for (int j = 1; j <= a[0]; j++)
cin >> a[j];
memset(dp, INF, sizeof(dp));
dp[0] = 0;
int now = 0;
for (int j = 1; j <= s*a[a[0]]+1; j++)
{
for (int k = 1; k <= a[0] && j >= a[k]; k++)
dp[j] = min(dp[j], dp[j - a[k]] + 1);
if (dp[j]>s)
{
now = j - 1;
break;
}
}
if (now > best) //此时的最大连续邮资大于了之前的
{
best = now;
number = a[0];
Max = a[a[0]];
memcpy(ans, a, sizeof(a));
}
else if (now == best) //如果相等时
{
if (a[0] < number) //首先考虑邮票数量少的
{
number = a[0];
Max = a[a[0]];
memcpy(ans, a, sizeof(a));
}
else if (a[a[0]] < Max) //如果邮票数量一样多,则优先考虑邮票最大的那张更小的
{
Max = a[a[0]];
memcpy(ans, a, sizeof(a));
}
}
}
printf("max coverage =%4d :", best);
for (int i = 1; i <= number; i++)printf("%3d", ans[i]);
puts("");
}
return 0;
}