非常经典的题目 经典到我忍不住把题面也要放上来
邮局发行一套票面有n(0<n<=10)种不同面值的邮票。若限每封信所贴的邮票张数不得超过m枚存在整数r使得用不超过m(0<m<=2n)枚的邮票可以贴出连续整数1,2,3,…,r值来,找出这种面值数,使得r值最大。
算是搜索+dp的集合 想清楚了表达起来非常爽
回溯的方式简直暴力又神奇 然而最可怕的是数组还不能开到外面(被坑了一上午
自己一开始想到了dp的推展 然而忘记了自己在做搜索专题
下面这个这是错的qaq 不过dp的那一部分是正确的
1 for (int i=2;i<=n;++i){ 2 for(int j=a[i-1][1]+1;j>a[i-1][0];--j){ 3 memset(c,0x7f,sizeof(c)); 4 for (int k=0;k<=a[i-1][1];++k) c[k]=b[k]; 5 int anss=-1; 6 for (int k=0;k<a[i-1][1];++k) 7 for (int l=1;l<=m-b[k];++l) c[k+l*j]=min(c[k+l*j],c[k]+l); 8 for (int k=a[i-1][1]+1;k<=j*m+1;++k) if (c[k]==2139062143) {anss=k-1;break;} 9 if (anss>a[i][1]) a[i][1]=anss,a[i][0]=j; 10 } 11 ans=max(ans,a[i][1]); 12 for (int k=0;k<=a[i-1][1];++k) 13 for (int l=1;l<=m-b[k];++l) b[k+l*a[i][0]]=min(b[k+l*a[i][0]],b[k]+l); 14 }
下面是打得很丑的正解qwq
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<algorithm> 6 #include<string> 7 #define INF 1000000 8 using namespace std; 9 int a[40][2]; 10 int n,m,ans; 11 int b[2000]; 12 void dfs(int x){ 13 if (x==n+1){ 14 ans=max(ans,a[x-1][1]); 15 return ; 16 } 17 int c[2000];//一定不要定义出去了qaq 18 memcpy(c,b,sizeof(b)); 19 for (int i=a[x-1][0]+1;i<=a[x-1][1]+1;++i){ 20 a[x][0]=i; 21 for (int j=0;j<=a[x-1][0]*m;++j){ 22 if (b[j]>=m) continue; 23 for (int k=1;k<=m-b[j];++k){ 24 b[j+k*i]=min(b[j+k*i],b[j]+k); 25 } 26 } 27 int r=a[x-1][1]+1; 28 while (b[r]!=INF) r++; 29 a[x][1]=r-1; 30 dfs(x+1); 31 memcpy(b,c,sizeof(c)); 32 } 33 } 34 int main(){ 35 freopen ("3.in","r",stdin); 36 freopen ("3.out","w",stdout); 37 scanf("%d%d",&n,&m); 38 a[1][0]=1,a[1][1]=m; 39 for (int i=1;i<=2000;++i) b[i]=INF; 40 for (int i=0;i<=m;++i) b[i]=i; 41 dfs(2); 42 cout<<ans; 43 return 0; 44 }
时间: 2024-11-02 11:39:56