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;
}
求从左上角到右下角所经过的数字之积末尾所含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;
}
相关文章推荐
- DZY Loves Chessboard
- hznu 1164 Unidirectional TSP(记录状态的DP)
- 【web安全】第六弹:手工SQL注入详解
- Redis集群部署(一)
- win7及以上版本USB2.0接口小提速
- 共享内存
- pm2 安装使用
- 使用python进行图像处理的基本方法
- LeetCode 之 Compare Version Numbers — C 实现
- 压缩与归档命令
- 电缆的特性阻抗
- poj 3669 bfs
- C语言如何调用 memcpy 函数 实现内存拷贝
- HDFS-datanode数据块部分笔记
- 安全测试之一:HTTP响应头拆分/CRLF注入详解
- 鹅厂2015实习生笔试题
- Windows 7双击文件夹/分区总是新窗口打开的解决方法[转]
- POJ 2104 区间第K大值(划分树做法)
- ASP.NET使用RadioButton控件
- IP、TCP、UDP、ICMP头详解