>动态规划 4.26

动态规划 4.26

CF2B The least round way(数论+dp)

原题链接

题意:

题目描述

给定由非负整数组成的n×n 的正方形矩阵,你需要寻找一条路径:

以左上角为起点

每次只能向右或向下走

以右下角为终点 并且,如果我们把沿路遇到的数进行相乘,积应当是最小“round”,换句话说,应当以最小数目的0的结尾.

输入格式

第一行包含一个整数 n (2≤n≤1000),n 为矩阵的规模,接下来的n行包含矩阵的元素(不超过10^9的非负整数).

输出格式

第一行应包含最小尾0的个数,第二行打印出相应的路径(译注:D为下,R为右)

思路:

结尾包含0的话说明有2和5相乘,那么结尾0的个数为2的个数和5的个数的最小值。
对于每一个数都获取他的因子2和因子5的个数,在看是从左边转移还是上边转移过来更优,记录路径即可。

注意特判的点就是如果该列表有个数为0的话,答案就是经过这个数的路径。

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int>PII;
#define I_int ll
#define x  first
#define y  second
#define PI acos(-1)
inline ll read()
{
    ll x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
char F[200];
inline void out(I_int x) {
    if (x == 0) return (void) (putchar('0'));
    I_int tmp = x > 0 ? x : -x;
    if (x < 0) putchar('-');
    int cnt = 0;
    while (tmp > 0) {
        F[cnt++] = tmp % 10 + '0';
        tmp /= 10;
    }
    while (cnt > 0) putchar(F[--cnt]);
    cout<<endl;
}

const int maxn=2e5+100;
int n,dp[1100][1100][2];
int pre[1100][1100][2],k;
void dfs(int x,int y){
	if(x==1&&y==1) return ;
	if(pre[x][y][k]){
		dfs(x-1,y);
		cout<<"D";
	}
	else{
		dfs(x,y-1);
		cout<<"R";
	}
	
}
int main(){
	cin>>n;
	int pos=-1;
	for(int i=2;i<=n;i++){
		dp[i][0][0]=dp[0][i][0]=0x3f3f3f3f;
		dp[0][i][1]=dp[i][0][1]=0x3f3f3f3f;
	}
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++){
			int x;cin>>x;
			if(!x){
				pos=i;continue;
			}
			int y=x;
			while(y%5==0){
				dp[i][j][1]++;
				y/=5;
			}
			y=x;
			while(y%2==0){
				dp[i][j][0]++;y/=2;
			}
		}
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			for(int k=0;k<2;k++)
				if(dp[i-1][j][k]<dp[i][j-1][k]){
					dp[i][j][k]+=dp[i-1][j][k];
					pre[i][j][k]=1;
				}
				else{
					dp[i][j][k]+=dp[i][j-1][k];
					pre[i][j][k]=0;
				}
	k=0;
	if(dp[n][n][0]>dp[n][n][1]) k=1;
	if(pos!=-1&&dp[n][n][k]>1){
		puts("1");
		for(int i=1;i<pos;i++) cout<<"D";
		for(int i=1;i<n;i++) cout<<"R";
		for(int i=pos;i<n;i++) cout<<"D";
		return 0;
	}
	cout<<dp[n][n][k]<<endl;
	dfs(n,n);
	return 0;
}

原文地址:https://www.cnblogs.com/OvOq/p/14706385.html