zoukankan      html  css  js  c++  java
  • CF 2B. The least round way【dp】

    题目链接
    思路
    求所经过路径乘积结果为0的最少数目的路径。
    假设已知所经过的路径以及每一个格子内的值,那么答案可以表示为(ans = x_1*x_2*x_3*x_4...*x_n),对每一个值进行质因子分解,那么答案数字对0的贡献仅有一种情况,即(2*5=10)这种情况。所以只要考虑从((1,1))走到((n,n))的路径上质因子(2)(5)数量更少的路径。
    (dp[i][j][x]:)表示从((1,1))走到((i,j))的路径中,(x)出现的最少次数。
    转移方向只要考虑从左边走过来还是往右边走过来即可。
    转移方程:
    (dp[i][j][x]=min(dp[i-1][j][x],dp[i][j-1][x])+cnt[i][j][x])
    (cnt[i][j][x]:)(a[i][j])这个数字由几个(x)组成。
    这边的x只要统计2和5即可。
    特判一种情况,就是某一个格子内的数字为0的情况。这样的话答案为1,当且仅当(min(dp[n][n][2],dp[n][n][5])>1)的情况下考虑。
    代码

    #include<bits/stdc++.h>
    using namespace std;
    
    typedef long long LL;
    typedef pair<int, int> PII;
    const int N = 1000 + 10;
    #define gcd __gcd
    const int mod = 1e9 + 7;
    const int inf = 0x3f3f3f3f;
    
    int num[N][N][6];
    int dp[N][N][6];
    PII pos;
    
    void print(int x, int y, int t) {
    	if(x == 1 && y == 1) return;
    	if(x > 1 && dp[x][y][t] == dp[x - 1][y][t] + num[x][y][t]) {
    		print(x - 1, y, t);
    		printf("D");
    	}
    	else {
    		print(x, y - 1, t);
    		printf("R");
    	}
    }
    
    void solve() {
    	int n;
    	scanf("%d", &n);
    	bool flag = false;
    
    	for(int i = 2; i <= n; i++) {
    		dp[0][i][2] = dp[0][i][5] = inf;
    		dp[i][0][2] = dp[i][0][5] = inf;
    	}
    
    	for(int i = 1; i <= n; i++) {
    		for(int j = 1; j <= n; j++) {
    			int x;
    			scanf("%d", &x);
    			if(x == 0) {
    				pos = {i, j};
    				flag = true;
    				continue;
    			}
    			while(x % 2 == 0) {
    				num[i][j][2]++;
    				x /= 2;
    			}
    			while(x % 5 == 0) {
    				num[i][j][5]++;
    				x /= 5;
    			}
    			dp[i][j][2] = min(dp[i - 1][j][2], dp[i][j - 1][2]) + num[i][j][2];
    			dp[i][j][5] = min(dp[i - 1][j][5], dp[i][j - 1][5]) + num[i][j][5];
    		}
    	}
    	if(flag && min(dp[n][n][2], dp[n][n][5]) > 1) {
    		puts("1");
    		for(int i = 1; i < pos.first; i++) {
    			printf("D");
    		}
    		for(int i = 1; i < pos.second; i++) {
    			printf("R");
    		}
    		for(int i = 1; i <= n - pos.first; i++) {
    			printf("D");
    		}
    		for(int i = 1; i <= n - pos.second; i++) {
    			printf("R");
    		}
    		return;
    	}
    	printf("%d
    ", min(dp[n][n][2], dp[n][n][5]));
    	if(dp[n][n][2] < dp[n][n][5]) print(n, n, 2);
    	else print(n, n, 5);
    }
    
    int main() {
    	// freopen("in.txt", "r", stdin);
    	// int t; cin >> t; while(t--)
    	solve();
    	return 0;
    }
    
  • 相关阅读:
    JS编码解码详解
    web的几种返回顶部
    图片的懒加载的两种效果
    获取两个日期差
    C#虚方法
    依赖注入(DI)和Ninject
    在应用程序级别之外使用注册为 allowDefinition='MachineToApplication' 的节是错误的
    PetShop的系统架构设计
    C#综合揭秘——细说多线程(下)
    C# Socket编程(4)初识Socket和数据流
  • 原文地址:https://www.cnblogs.com/ZX-GO/p/14736278.html
Copyright © 2011-2022 走看看