dp 2016.7.29
来源:互联网 发布:怎样领淘宝内部优惠卷 编辑:程序博客网 时间:2024/06/05 12:49
1、Codeforces_2B The least round way
参考:http://www.cnblogs.com/zjbztianya/p/3271449.html
题意:
给定一个N*N的格子,每个格子里有一个非负数
要求你找出从左上角到右下角的一条路径,使得它满足路径上的格子里的数全部乘起来的积尾部0最少
解题思路:
如果要产生0肯定是2*5得出来的,最终的乘积可以表示为 2 ^ x * 5 ^ y * C,那么零的个数就是 min(x, y)
我们可以先对每个格子里的数预处理下,计算出2和5的个数来
然后 dp 分别求出 2 和 5 的最小个数然后选两者中的最小值,这个 dp 还是比较简单的
还有一个要注意的问题就是如果某个格子的数字为0的情况,这个需要特殊判断一下,我们可以把它当做10,如果最后的结果0的个数大于1则直接输出尾部0的个数为1即可
#include <iostream>#include <cstdio>#include <cstring>#include <cstdlib>#include <algorithm>#include <queue>#include <vector>#include <stack>#include <map>#include <cmath>#include <cctype>using namespace std;typedef long long ll;typedef unsigned long long ull;typedef unsigned int uint;const ull mod = 1e9 + 7;const int INF = 0x7fffffff;const int maxn = 1e3 + 10;int n;int dp_2[maxn][maxn], dp_5[maxn][maxn];bool flag = false;int zero_x, zero_y;bool turn_2[maxn][maxn], turn_5[maxn][maxn];string s;int x;int main(){#ifdef __AiR_H freopen("in.txt", "r", stdin);#endif // __AiR_H scanf("%d", &n); memset(dp_2, 0, sizeof(dp_2)); memset(dp_5, 0, sizeof(dp_5)); memset(turn_2, false, sizeof(turn_2)); //默认向下 memset(turn_5, false, sizeof(turn_5)); for (int i = 0; i < n; ++i) { for (int j = 0; j < n; ++j) { scanf("%d", &x); if (x == 0) { flag = true; zero_x = i; zero_y = j; dp_2[i][j] = dp_5[i][j] = 1; } else { while (!(x & 1)) { ++dp_2[i][j]; x >>= 1; } while (x%5 == 0) { ++dp_5[i][j]; x /= 5; } } } } for (int i = 0; i < n; ++i) { for (int j = 0; j < n; ++j) { int t1 = INF, t2 = INF; if (i == 0 && j == 0) { t1 = t2 = 0; } if (i != 0 && dp_2[i-1][j] < t1) { t1 = dp_2[i-1][j]; } if (j != 0 && dp_2[i][j-1] < t1) { t1 = dp_2[i][j-1]; turn_2[i][j] = true; } if (i != 0 && dp_5[i-1][j] < t2) { t2 = dp_5[i-1][j]; } if (j != 0 && dp_5[i][j-1] < t2) { t2 = dp_5[i][j-1]; turn_5[i][j] = true; } dp_2[i][j] += t1; dp_5[i][j] += t2; } } int Min = min(dp_2[n-1][n-1], dp_5[n-1][n-1]); if (flag && Min > 1) { printf("1\n"); for (int i = 0; i < zero_y; ++i) { printf("R"); } for (int i = 0; i < zero_x; ++i) { printf("D"); } for (int i = zero_y; i < n-1; ++i) { printf("R"); } for (int i = zero_x; i < n-1; ++i) { printf("D"); } printf("\n"); } else { int i = n-1, j = n-1; if (Min == dp_5[n-1][n-1]) { while (i > 0 || j > 0) { if (turn_5[i][j]) { s += 'R'; --j; } else { s += 'D'; --i; } } } else { while (i > 0 || j > 0) { if (turn_2[i][j]) { s += 'R'; --j; } else { s += 'D'; --i; } } } reverse(s.begin(), s.end()); cout << Min << endl; cout << s << endl; } return 0;}
2、SGU 116 Index of super-prime
dp[j] 表示和为 j 时使用的最少的超级素数的个数
#include <iostream>#include <cstdio>#include <cstring>#include <cstdlib>#include <algorithm>#include <queue>#include <vector>#include <stack>#include <map>#include <cmath>#include <cctype>using namespace std;typedef long long ll;typedef unsigned long long ull;typedef unsigned int uint;const ull mod = 1e9 + 7;const int INF = 0x7fffffff;const int maxn = 1e5 + 10;bool vis[maxn];int Count = 1;int Prime[9600];int Super[1200];int Super_Count = 0;int dp[maxn];int pre[maxn];int ans[maxn];int ans_Count = 0;void Init(void);bool cmp(int x, int y);int main(){#ifdef __AiR_H freopen("in.txt", "r", stdin);// freopen("out.txt", "w", stdout);#endif // __AiR_H Init(); int N; while (scanf("%d", &N) != EOF) { memset(pre, 0, sizeof(pre)); memset(dp, 0, sizeof(dp)); ans_Count = 0; int t = lower_bound(Super, Super+Super_Count, N) - Super; for (int i = 0; i <= t; ++i) { dp[Super[i]] = 1; pre[Super[i]] = 0; for (int j = 1; j <= N-Super[i]; ++j) { if (dp[j] != 0) { if (dp[Super[i]+j] == 0 || dp[Super[i]+j] > dp[j] + 1) { dp[Super[i]+j] = dp[j] + 1; pre[Super[i]+j] = j; } } } } if (dp[N] == 0) { printf("0\n"); } else { int N_t = N; while (N_t != 0) { ans[ans_Count++] = N_t - pre[N_t]; N_t = pre[N_t]; } printf("%d\n", ans_Count); sort(ans, ans+ans_Count, cmp); printf("%d", ans[0]); for (int i = 1; i < ans_Count; ++i) { printf(" %d", ans[i]); } printf("\n"); } } return 0;}void Init(void){ memset(vis, false, sizeof(vis)); for (int i = 2; i < maxn; ++i) { if (!vis[i]) { vis[i] = true; Prime[Count++] = i; int j = i*2; while (j < maxn) { vis[j] = true; j += i; } } } for (int i = 1; i < Count; ++i) { int t = lower_bound(Prime, Prime+Count, i) - Prime; if (Prime[t] == i) { Super[Super_Count++] = Prime[i]; } }}bool cmp(int x, int y){ return (x > y);}
3、最大上升子序列和
- 描述
一个数的序列bi,当b1 < b2 < ... < bS的时候,我们称这个序列是上升的。对于给定的一个序列(a1, a2, ...,aN),我们可以得到一些上升的子序列(ai1, ai2, ..., aiK),这里1 <= i1 < i2 < ... < iK <= N。比如,对于序列(1, 7, 3, 5, 9, 4, 8),有它的一些上升子序列,如(1, 7), (3, 4, 8)等等。这些子序列中序列和最大为18,为子序列(1, 3, 5, 9)的和.
你的任务,就是对于给定的序列,求出最大上升子序列和。注意,最长的上升子序列的和不一定是最大的,比如序列(100, 1, 2, 3)的最大上升子序列和为100,而最长上升子序列为(1, 2, 3)- 输入
- 输入的第一行是序列的长度N (1 <= N <= 1000)。第二行给出序列中的N个整数,这些整数的取值范围都在0到10000(可能重复)。
- 输出
- 最大上升子序列和
- 样例输入
71 7 3 5 9 4 8
- 样例输出
18
解题思路:
dp[j] 表示以 num[j] 结尾的最大上升子序列和
#include <iostream>#include <cstdio>#include <cstring>#include <cstdlib>#include <algorithm>#include <queue>#include <vector>#include <stack>#include <map>#include <cmath>#include <cctype>using namespace std;typedef long long ll;typedef unsigned long long ull;typedef unsigned int uint;const ull mod = 1e9 + 7;const int INF = 0x7fffffff;const int maxn = 1e3 + 10;int num[maxn];int N;int dp[maxn];int main(){#ifdef __AiR_H freopen("in.txt", "r", stdin);#endif // __AiR_H scanf("%d", &N); for (int i = 0; i < N; ++i) { scanf("%d", &num[i]); } memset(dp, 0, sizeof(dp)); int ans = 0; for (int i = 0; i < N; ++i) { int Max = 0; for (int j = 0; j < i; ++j) { if (num[j] < num[i]) { if (dp[j] > Max) { Max = dp[j]; } } } dp[i] = num[i] + Max; if (dp[i] > ans) { ans = dp[i]; } } printf("%d\n", ans); return 0;}
4、HDU 5748 Bellovin
一道裸的 nlogn 的 LIS
#include <iostream>#include <cstdio>#include <cstring>#include <cstdlib>#include <algorithm>#include <queue>#include <vector>#include <stack>#include <map>#include <cmath>#include <cctype>using namespace std;typedef long long ll;typedef unsigned long long ull;typedef unsigned int uint;const ull mod = 1e9 + 7;const int INF = 0x7fffffff;const int maxn = 1e5 + 10;int a[maxn];int n;int B[maxn];int dp[maxn];int main(){#ifdef __AiR_H freopen("in.txt", "r", stdin);#endif // __AiR_H int T; scanf("%d", &T); while (T--) { scanf("%d", &n); for (int i = 1; i <= n; ++i) { scanf("%d", &a[i]); } int Count = 0; memset(B, 0, sizeof(B)); memset(dp, 0, sizeof(dp)); for (int i = 1; i <= n; ++i) { if (Count == 0 || a[i] > B[Count-1]) { B[Count++] = a[i]; dp[i] = Count; } else { int pos = lower_bound(B, B+Count, a[i]) - B; B[pos] = a[i]; dp[i] = pos+1; } } printf("%d", dp[1]); for (int i = 2; i <= n; ++i) { printf(" %d", dp[i]); } printf("\n"); } return 0;}
5、HDU 5763 Another Meaning
匹配用暴力(比如 string 类的 find)也能过,还可以用 KMP 或者其它方法
具体是怎么 dp 的我说不很清楚。。。所以干脆根据样例一步一步画出来了
当 A = hehehehe,B = hehe
dp[0] :
*hehe
dp[1] :
*hehe
dp[2] :
dp[i-1] : *hehe
+1 : he*he
dp[3] :
*hehe he*he
dp[4] :
dp[i-1] : *hehe he*he
dp[i-len_B] : **
+1 : hehe*
dp[5] = dp[6] = d[7] :
*hehe he*he ** hehe*
ans:
dp[7] : *hehe he*he ** hehe*
+1 hehehehe
当 A = aaaab,B = a
dp[0] :
*aaab
dp[1] :
+d[i-1] : *aaab
+dp[i-len_B] : **aab
+1 : a*aab
dp[2] :
+dp[i-1] : *aaab **aab a*aab
+dp[i-len_B] : *a*ab ***ab a**ab
+1 : aa*ab
dp[3] :
+dp[i-1] : *aaab **aab a*aab *a*ab ***ab a**ab aa*ab
+dp[i-len_B] : *aa*b ***ab a*a*b *a**b ****b a***b aa**b
+1 : aaa*b
dp[4] :
*aaab **aab a*aab *a*ab ***ab a**ab aa*ab *aa*b ***ab a*a*b *a**b ****b a***b aa**b aaa*b
ans :
dp[4] : *aaab **aab a*aab *a*ab ***ab a**ab aa*ab *aa*b ***ab a*a*b *a**b ****b a***b aa**b aaa*b
+1 : aaaab
#include <iostream>#include <cstdio>#include <cstring>#include <cstdlib>#include <algorithm>#include <queue>#include <vector>#include <stack>#include <map>#include <cmath>#include <cctype>#include <bitset>using namespace std;typedef long long ll;typedef unsigned long long ull;typedef unsigned int uint;typedef pair<int, int> Pair;const int mod = 1e9 + 7;const int INF = 0x7fffffff;const int maxn = 1e5 + 10;string A, B;bool vis[maxn];int dp[maxn];int main(){#ifdef __AiR_H freopen("in.txt", "r", stdin);#endif // __AiR_H int T; scanf("%d", &T); int Case= 0; while (T--) { memset(vis, false, sizeof(vis)); cin >> A >> B; int len_B = B.length(); int len_A = A.length(); size_t pos = A.find(B, 0); while (pos != string::npos) { vis[pos] = true; pos = A.find(B, pos+1); } for (int i = 0; i < len_A; ++i) { if (vis[i]) { if (i == 0) { dp[i] = 1; } else if (i < len_B) { dp[i] = dp[i-1] + 1; dp[i] %= mod; } else { dp[i] = dp[i-1] + dp[i-len_B] + 1; dp[i] %= mod; } } else { if (i == 0) { dp[0] = 0; } else { dp[i] = dp[i-1]; } } } printf("Case #%d: %d\n", ++Case, (dp[len_A-1]+1) % mod); } return 0;}
#include <iostream>#include <cstdio>#include <cstring>#include <cstdlib>#include <algorithm>#include <queue>#include <vector>#include <stack>#include <map>#include <cmath>#include <cctype>#include <bitset>using namespace std;typedef long long ll;typedef unsigned long long ull;typedef unsigned int uint;typedef pair<int, int> Pair;const int mod = 1e9 + 7;const int INF = 0x7fffffff;const int maxn = 1e5 + 10;char A[maxn], B[maxn];bool vis[maxn];int dp[maxn];int Next[maxn];int len_A, len_B;void Build_Next(void);void Match(void);int main(){#ifdef __AiR_H freopen("in.txt", "r", stdin);#endif // __AiR_H int T; scanf("%d", &T); int Case= 0; while (T--) { memset(vis, false, sizeof(vis)); scanf("%s%s", A, B); len_A = strlen(A), len_B = strlen(B); Build_Next(); Match(); for (int i = 0; i < len_A; ++i) { if (vis[i]) { if (i == 0) { dp[i] = 1; } else if (i < len_B) { dp[i] = dp[i-1] + 1; dp[i] %= mod; } else { dp[i] = dp[i-1] + dp[i-len_B] + 1; dp[i] %= mod; } } else { if (i == 0) { dp[0] = 0; } else { dp[i] = dp[i-1]; } } } printf("Case #%d: %d\n", ++Case, (dp[len_A-1]+1) % mod); } return 0;}void Build_Next(void){ int i = 0; int t = Next[0] = -1; while (i < len_B-1) { if (t < 0 || B[i] == B[t]) { ++i; ++t; Next[i] = (B[i] != B[t] ? t : Next[t]); } else { t = Next[t]; } }}void Match(void){ int i = 0; while (1) { int j = 0; while (j < len_B && i < len_A) { if (j < 0 || A[i] == B[j]) { ++i; ++j; } else { j = Next[j]; } } if (i-j < len_A-len_B+1) { vis[i-j] = true; i = i-j+1; } else { break; } }}
- dp 2016.7.29
- WOJ-29 Werewolf(DP)
- dp
- dp
- dp
- 【DP】
- dp
- dp
- DP
- DP
- DP
- DP
- DP
- dp
- DP
- dp
- DP
- DP
- Ubnutu 部署 k8s 的一个坑
- python 进程
- latex中定理定义等数学环境下的字体设置
- char *p 和 cha'r p[10]的区别/sizeof和strlen的区别
- 自定义UITableView索引动画,实现饿了么菜单效果
- dp 2016.7.29
- python 开发模拟板Web QQ(四)
- 用srand, rand产生的随机数有隐患------还是用利用linux的/dev/urandom文件产生随机数吧
- Zookeeper 节点操作,storm 启动
- spring boot 学习笔记(006)log
- 1011 Problem K
- Shuffle阶段的自我理解
- 任务切换——《x86汇编语言:从实模式到保护模式》读书笔记38
- Swift语言中的控制语句和函数