• 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;
    }
    
  • 相关阅读:
    101. Symmetric Tree(js)
    100. Same Tree(js)
    99. Recover Binary Search Tree(js)
    98. Validate Binary Search Tree(js)
    97. Interleaving String(js)
    96. Unique Binary Search Trees(js)
    95. Unique Binary Search Trees II(js)
    94. Binary Tree Inorder Traversal(js)
    93. Restore IP Addresses(js)
    92. Reverse Linked List II(js)
  • 原文地址:https://www.cnblogs.com/ZX-GO/p/14736278.html
Copyright © 2020-2023  润新知