类计数类DP(其实就是但是懒得往里面挪了....)
一:结合数学知识(废话)vjudge
2021级DP题单 - Virtual Judge (vjudge.net)
就是给你n个数,选出k个*起来
让末尾0个数最多
思路:
一开始找数和数之间的规律,后来找蒙了
想:怎么*出0,质因数分解,只有2*5有0(所有质数)
所以我只需要统计每个数分解出的2和5个数
一一匹配最大时结果最大
怎么选数?
DP
dp[i][j][k]:前i个数选了j个,分解出k个5,最多分解的2的个数//为什么是最多,不应该刚好匹配吗(宁多不少) max(dp[i-1][j][k],dp[i-1][j-1][k-div5[i]]+div2[i]) //这个数选或者不选
优化:1.空间不够,滚动数组优化
2.k这一位5比2好(5更少)
const int WR=1001000;ll INF=1e18; int n,k; ll A[210],B[210]; int d5[210],d2[210]; int dp[210][6000],tmp[210][6000]; int tot_5; inline void get2_5(int nd,ll x) { while(x!=0&&x%2==0) { d2[nd]++; x/=2; } while(x!=0&&x%5==0) { d5[nd]++; x/=5; } tot_5+=d5[nd]; }//18*200 int main() { // freopen("makeans.txt","r",stdin); // freopen("fire.out","w",stdout); n=re();k=re(); _f(i,1,n) { scanf("%I64d",&A[i]); get2_5(i,A[i]); // chu("5:%d 2:%d\n",d5[i],d2[i]); } memset(dp,-0x3f,sizeof(dp));//不存在的状态也要考虑进去 dp[1][d5[1]]=d2[1];//第一个初始化一下 ,如果第一个数不选呢 dp[0][0]=0; for(int i=2;i<=n;i++)//前i个数 { //chu("round:%d\n",i); memcpy(tmp,dp,sizeof(dp)); for(int j=1;j<=k;j++)//选j个 { for(int o=0;o<=tot_5;o++) { dp[j][o]=tmp[j][o]; // chu("不选:dp[%d][%d]:%d\n",j,o,dp[j][o]); if(j-1>=0&&(o-d5[i])>=0)dp[j][o]=max(tmp[j][o],tmp[j-1][o-d5[i]]+d2[i]); // chu("选:(如果更优):%d\n",dp[j][o]); } } } int maxans=0; //从dp[k]里面选 _f(i,0,tot_5) { // chu("dp[%d][%d]:%d\n",k,i,dp[k][i]); int minx=min(dp[k][i],i); maxans=max(minx,maxans); } chu("%d",maxans); return 0; } /* 上午是DP专题 下午复习一下图论 5 3 15 16 3 25 9 3 2 50 4 20 */
二:多维度(数据范围足够小)POJ2279
蓝书DP
int lim[6]; int dp[32][32][32][32][32]; int main() { // freopen("makeans.txt","r",stdin); // freopen("fire.out","w",stdout); int n=re(),k=re(); _f(i,1,k)lim[i]=re(); dp[0][0][0][0][0]=1; for(int i=0;i<=lim[1];i++)//第一排 for(int j=0;j<=lim[2];j++) for(int k=0;k<=lim[3];k++) for(int m=0;m<=lim[4];m++) for(int l=0;l<=lim[5];l++)//第5排 { if(i+1<=lim[1])dp[i+1][j][k][m][l]+=dp[i][j][k][m][l]; if(j+1<=lim[2]&&j<i)dp[i][j+1][k][m][l]+=dp[i][j][k][m][l]; if(k+1<=lim[3]&&k<j)dp[i][j][k+1][m][l]+=dp[i][j][k][m][l]; if(m+1<=lim[4]&&m<k)dp[i][j][k][m+1][l]+=dp[i][j][k][m][l]; if(l+1<=lim[5]&&l<m)dp[i][j][k][m][l+1]+=dp[i][j][k][m][l]; } chu("%d",dp[lim[1]][lim[2]][lim[3]][lim[4]][lim[5]]); return 0; }
浙公网安备 33010602011771号