3 12 1 24 6 3 4 4 4 16 0
Case #1: 3
解析:
12可以分为2*2*3;
那么答案就是统计min(2的个数/2,3的个数)的最大值;
如果直接记录2的个数,3的个数为状态的话,50*50*乘积中2的幂次*3的幂次,内存不够。
于是想到只将3的幂次作为一种状态,然后记录沿途能达到的2的个数。
状态方程
F[I][J][K]表示能够有2因子的个数,没有就为-1;
Temp=max(F[I-1][J][K],F[I]J-1][K]);
F[I][J][K+MP[I][J].Y]=TEMP+MP[I][J].X;
注意边界;
具体看代码了;
#include<cstdio> #include<cstring> #include<string> #include<queue> #include<algorithm> #include<vector> #include<set> #include<map> #define INF 999999999 #define N 100000 using namespace std; struct node { int x,y; }mp[51][51]; int dp[51][51][2000]; int main() { int t=0; int n; while (scanf("%d",&n)!=EOF&&n){ printf("Case #%d: ",++t); memset(mp,0,sizeof(mp)); memset(dp,-1,sizeof(dp));//初始化为-1, for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) { int xx,yy; scanf("%d",&xx); yy=xx; while (yy%2==0)//记录元素是2的多少次方 { mp[i][j].x++; yy/=2; } while (xx%3==0)记录元素是3的多少次放 { mp[i][j].y++; xx/=3; } } dp[0][0][0]=0; for (int i=1;i<=n;i++) dp[0][i][0]=0,dp[i][0][0]=0;//边界 for (int i=1;i<=n;i++)//状态转移 for (int j=1;j<=n;j++) for (int k=0;k<=1200;k++)//1200是自己随便写的一个状态,可能实际没有这么多 { int temp=max(dp[i-1][j][k],dp[i][j-1][k]);//考虑DP[I-1][J][K],DP[I][J-1][K]都可能为-1 if (temp>-1) dp[i][j][k+mp[i][j].y]=mp[i][j].x+temp; } int ans=0; for (int i=0;i<=1200;i++) ans=max(ans,min(dp[n][n][i]/2,i)); printf("%d\n",ans); } return 0; }
原文:http://www.cnblogs.com/forgot93/p/3819024.html