UVa 242 - Stamps and Envelope Size(DP)

给出一个 s ,然后给出 n 组邮票,问那一组可以凑出最大连续邮资。
对每一组邮票,求出当邮资为i时需要邮票数的最小值 d [ i ] ,边界为 d [ 0 ] = 0 、 d [ i ] > s 时break。类似于背包问题的求法,具体方法见代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=1010;
int d[maxn],ans[20],num[20],a[20][20];
int main(){
int s;
while(~scanf("%d",&s)&&s){
int n;scanf("%d",&n);
for(int i=1;i<=n;++i){
scanf("%d",&num[i]);
for(int j=1;j<=num[i];++j) scanf("%d",&a[i][j]);
memset(d,0x3f,sizeof(d));
d[0]=0;
for(int j=1;j<maxn;++j){
for(int k=1;k<=num[i]&&j-a[i][k]>=0;++k)
d[j]=min(d[j],d[j-a[i][k]]+1);
if(d[j]>s){ans[i]=j-1;break;}
}
}
int best=-1,pos=0;
for(int i=1;i<=n;++i){
if(ans[i]>best) best=ans[i],pos=i;
else if(ans[i]==best){
if(num[i]<num[pos]) pos=i;
else if(num[i]==num[pos]){
bool ok=false;
for(int j=num[i];j>0;--j)
if(a[i][j]!=a[pos][j]){
ok=a[i][j]<a[pos][j];
break;
}
if(ok) pos=i;
}
}
}
printf("max coverage =%4d :",ans[pos]);
for(int i=1;i<=num[pos];i++)
printf("%3d",a[pos][i]);
printf("\n");
}
return 0;
}

** 本文迁移自我的CSDN博客,格式可能有所偏差。 **