您的位置:首页 > 其它

cf contest2 B

2015-06-11 20:43 309 查看
http://codeforces.com/problemset/problem/2/B

求从左上角到右下角所经过的数字之积末尾所含0最小的个数

10=2*5

dp[i][j][0]代表走到i,j位置,所得2的最小和,

dp[i][j][1]代表走到i,j位置,所得5的最小和,

最后得到的最小个数是min(dp

[0],dp

[1]);

还要用每个数初始化dp数组哦

但是可能会有0,这是一个trick;

如果存在零,那么最小个数一定是小于等于1

所以先判断是否有0存在,如果这个数字为0的,就将它改为10=2*5,

最后根据是否有零,判断就好

还要输出路径

输出有零的路径比较简单,可以一开始标记一个0的位置就行了

没有的零的话

就比较dp[i-1][j][0]和dp[i][j-1][0](也可能是1)

然后得到路径

#include <iostream>

#include <cstdio>

#include <algorithm>

#include <cstring>

using namespace std;

int n;

int flag=0,x,y;

int map[1001][1001];

int dp[1001][1001][2];

char ways[2002];

int main(void)

{

//freopen("in.txt","r",stdin);

cin >> n;

for(int i = 1;i<=n;i++)

for(int j = 1;j<=n;j++)

{

scanf("%d",&map[i][j]);

if(map[i][j]==0)x=i,y=j,flag=1,dp[i][j][0]=1,dp[i][j][1]=1;

int t = map[i][j];

while(t && t%2==0)dp[i][j][0]+=1,t/=2;.

while(t && t%5==0)dp[i][j][1]+=1,t/=5;

}

for(int i = 1;i<=n;i++)

for(int j = 1;j <=n;j++)

{

if(i-1 >= 1 && j-1 >=1)

{

dp[i][j][0]+=min(dp[i-1][j][0],dp[i][j-1][0]);

dp[i][j][1]+=min(dp[i][j-1][1],dp[i-1][j][1]);

}

else if(i-1>=1)

{

dp[i][j][0]+=dp[i-1][j][0];

dp[i][j][1]+=dp[i-1][j][1];

}

else if(j-1>=1)

{

dp[i][j][0]+=dp[i][j-1][0];

dp[i][j][1]+=dp[i][j-1][1];

}

}

int ans = dp

[0]>dp

[1]? 1 : 0;

int cnt = min(dp

[0],dp

[1]);

if(flag && cnt >= 1)

{

printf("1\n");

for(int i=1;i <= x-1;i++)

printf("D");

for(int i=1;i<=y-1;i++)

printf("R");

for(int i=x+1;i<=n;i++)

printf("D");

for(int i=y+1;i<=n;i++)

printf("R");

}

else

{

printf("%d\n",cnt);

int a = n,b = n;

int t = 0;

while(a > 1 && b > 1)

{

if(dp[a-1][b][ans] < dp[a][b-1][ans])

ways[t++]='D',a--;

else

ways[t++]='R',b--;

}

if(b != 1)

for(int i = 1; i<=b-1;i++)

ways[t++]='R';

if(a!=1)

for(int i= 1;i<=a-1;i++)

ways[t++]='D';

for(int i = t-1;i>=0;i--)

printf("%c",ways[i]);

}

return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: