| page | section | no | title | submit | ||||
| 113 | 1.5.1 | 例题1 | 括号序列 | POJ1141 | ||||
| 116 | 1.5.1 | 例题2 | 棋盘分割 | POJ1191 | ||||
| 117 | 1.5.1 | 例题3 | 决斗 | 117 | 1.5.1 | 例题4 | “舞蹈家”怀特先生 | ACM-ICPC Live Archive |
| 119 | 1.5.1 | 例题5 | 积木游戏 | http://202.120.80.191/problem.php?problemid=1244 | ||||
| 123 | 1.5.2 | 例题1 | 方块消除 | http://poj.org/problem?id=1390 | ||||
| 123 | 1.5.2 | 例题2 | 公路巡逻 | http://202.120.80.191/problem.php?problemid=1600 | ||||
| 125 | 1.5.2 | 例题3 | 并行期望值 | POJ1074 | ||||
| 131 | 1.5.2 | 例题6 | 不可分解的编码 | http://acmicpc-live-archive.uva.es/nuevoportal/data/problem.php?p=2475 | ||||
| 133 | 1.5.2 | 例题7 | 青蛙的烦恼 | http://codewaysky.sinaapp.com/problem.php?id=1014 | ||||
| 135 | 1.5.2 | 例题9 | 最优排序二叉树 | http://judge.noi.cn/problem?id=1059 | ||||
| 138 | 1.5.2 | 例题10 | Bugs公司 | POJ1038 | ||||
| 139 | 1.5.2 | 例题11 | 迷宫统计 | http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=70&page=show_problem&problem=1472 | ||||
| 142 | 1.5.2 | 例题12 | 贪吃的九头龙 | http://judge.noi.cn/problem?id=1043 | ||||
| 151 | 1.5.3 | 问题2 | 最长上升子序列问题 | http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=17&page=show_problem&problem=1475 | ||||
| 151 | 1.5.3 | 问题3 | 最优二分检索树 | http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=15&page=show_problem&problem=1245 | ||||
| 152 | 1.5.3 | 问题4 | 任务调度问题 | POJ1180 | ||||
| 121 | 1.5.1 | 1.5.8 | 艺术馆的火灾 | http://221.192.240.23:9088/showproblem?problem_id=1366 | ||||
| 144 | 1.5.2 | 1.5.10 | 快乐的蜜月 | http://judge.noi.cn/problem?id=1052 | ||||
| 145 | 1.5.2 | 1.5.12 | 佳佳的筷子 | http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=14&page=show_problem&problem=1212 | ||||
| 146 | 1.5.2 | 1.5.13 | 偷懒的工人 | POJ1337 | ||||
| 146 | 1.5.2 | 1.5.15 | 平板涂色 | POJ1691 | ||||
| 147 | 1.5.2 | 1.5.16 | 道路重建 | POJ1947 | ||||
| 147 | 1.5.2 | 1.5.17 | 圆和多边形 | http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1679 | ||||
| 148 | 1.5.2 | 1.5.18 | Jimmy落地 | POJ1661 | ||||
| 148 | 1.5.2 | 1.5.19 | 免费糖果 | http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=13&page=show_problem&problem=1059 | ||||
| 157 | 1.5.3 | 1.5.22 | 回文词 | POJ1159 | ||||
| 157 | 1.5.3 | 1.5.24 | 邮局 | POJ1160 | ||||
| 158 | 1.5.3 | 1.5.26 | 奶牛转圈 | POJ1946 | ||||
| 158 | 1.5.3 | 1.5.27 | 元件折叠 | http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=14&page=show_problem&problem=1180 |
现在开始训练一下DP:
pku 1141 Brackets Sequence
黑书上讲的第一个题目,题意就给出一个括号序列,包含有"(" ")" "[" "]" 求最少添加的括号数是的最终的序列是合法的并输出这个序列。
思路:
首先这里求解的话要使用递归的思路,这是动态规划产生的第一种动机,于是我们可以写出记忆化搜索。进行求解。
dp[l][r] = min(dp[l][r],dp[l + 1][r - 1])如果s[l]与s[r]匹配的话。
否则我们就将该序列分成两段分别求解(这也是求解DP线性模型的一种递归分解思路)
dp[l][r] = min(dp[l][r],dp[l][k] + dp[k + 1][r])
这里关键是怎么讲可行解输出呢?开始我是通过比较dp[l][r] 与 dp[l + 1][r -1] dp[l][k] + dp[k + 1][r]来判断的后来发现这样不对的 如果dp[l + 1][r - 1] = dp[l][k] + dp[k + 1][r]的话就会出现错误,而我们这里dp[l][r]确实从dp[l][k] + dp[k + 1][r]来的。所以,我们要另开一个二维数组记录每种最优状态的来源点。然后再递归的输出即可。
#include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <algorithm> #include <string> #include <set> #include <functional> #include <numeric> #include <sstream> #include <stack> #include <map> #include <queue> #define CL(arr, val) memset(arr, val, sizeof(arr)) #define lc l,m,rt<<1 #define rc m + 1,r,rt<<1|1 #define pi acos(-1.0) #define ll __int64 #define L(x) (x) << 1 #define R(x) (x) << 1 | 1 #define MID(l, r) (l + r) >> 1 #define Min(x, y) (x) < (y) ? (x) : (y) #define Max(x, y) (x) < (y) ? (y) : (x) #define E(x) (1 << (x)) #define iabs(x) (x) < 0 ? -(x) : (x) #define OUT(x) printf("%I64d\n", x) #define lowbit(x) (x)&(-x) #define Read() freopen("din.txt", "r", stdin) #define Write() freopen("dout.txt", "w", stdout); #define M 137 #define N 115 using namespace std; const int inf = 0x7f7f7f7f; const int mod = 1000000007; int dp[N][N]; char s[N]; int mk[N][N]; bool cmp(char a,char b) { if ((a == '(' && b == ')') || (a == '[' && b == ']')) return true; return false; } int dfs_DP(int l,int r) { int k; if (l > r) return 0; if (l == r) return (dp[l][r] = 1); if (dp[l][r] != inf) return dp[l][r]; if (cmp(s[l],s[r])) { if (l + 1 == r) { dp[l][r] = 0; mk[l][r] = -1; } else { dfs_DP(l + 1,r - 1); if (dp[l][r] > dp[l + 1][r - 1]) { dp[l][r] = dp[l + 1][r - 1]; mk[l][r] = -1; } // dp[l][r] = min(dp[l][r],dfs_DP(l + 1,r - 1)); // printf(">>>**%d %d %d %d\n",l,r,dp[l][r],dp[l + 1][r - 1]); } } for (k = l; k <= r - 1; ++k) { dfs_DP(l,k); dfs_DP(k + 1,r); if (dp[l][r] > dp[l][k] + dp[k + 1][r]) { dp[l][r] = dp[l][k] + dp[k + 1][r]; mk[l][r] = k; } // dp[l][r] = min(dp[l][r],dfs_DP(l,k) + dfs_DP(k + 1,r)); } return dp[l][r]; } void print(int l,int r) { if (l > r) return; if (l == r) { if (s[l] == '(' || s[l] == ')') printf("()"); else if (s[l] == '[' || s[l] == ']') printf("[]"); return; } if (cmp(s[l],s[r]) && mk[l][r] == -1) { printf("%c",s[l]); print(l + 1,r - 1); printf("%c",s[r]); } else { print(l,mk[l][r]); print(mk[l][r] + 1,r); } } int main() { // Read(); // Write(); int i,j; scanf("%s",s); int n = strlen(s); CL(mk,-1); for (i = 0; i <= n; ++i) { for (j = 0; j <= n; ++j) { dp[i][j] = inf; } } dfs_DP(0,n - 1); // printf("%d\n",dp[0][n - 1]); print(0,n - 1); printf("\n"); return 0; }
pku 1191 棋盘分割
思路:
棋盘横着切竖着切,然后递归将棋盘不断缩小到能够求解的状态。记忆化搜索。这里中间计算值可能会超0x7f7f7f7f,所以最大值取大一点。这里让哥条了很长时间。。
#include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <algorithm> #include <string> #include <set> #include <functional> #include <numeric> #include <sstream> #include <stack> #include <map> #include <queue> #define CL(arr, val) memset(arr, val, sizeof(arr)) #define lc l,m,rt<<1 #define rc m + 1,r,rt<<1|1 #define pi acos(-1.0) #define ll __int64 #define L(x) (x) << 1 #define R(x) (x) << 1 | 1 #define MID(l, r) (l + r) >> 1 #define Min(x, y) (x) < (y) ? (x) : (y) #define Max(x, y) (x) < (y) ? (y) : (x) #define E(x) (1 << (x)) #define iabs(x) (x) < 0 ? -(x) : (x) #define OUT(x) printf("%I64d\n", x) #define lowbit(x) (x)&(-x) #define Read() freopen("din.txt", "r", stdin) #define Write() freopen("dout.txt", "w", stdout); #define M 137 #define N 10 using namespace std; const int inf = 0x7f7f7f7f; const int mod = 1000000007; int mat[N][N]; int s[N][N][N][N]; int dp[N][N][N][N][20]; ll map[N][N]; int n; int DP(int x1,int y1,int x2,int y2,int no) { int x,y; if (no == 1) return dp[x1][y1][x2][y2][no]; if (dp[x1][y1][x2][y2][no] != -1) return dp[x1][y1][x2][y2][no]; int ans = 999999999; for (x = x1; x < x2; ++x) { ans = min(ans,min(DP(x1,y1,x,y2,no - 1) + s[x + 1][y1][x2][y2],DP(x + 1,y1,x2,y2,no - 1) + s[x1][y1][x][y2])); } for (y = y1; y < y2; ++y) { ans = min(ans,min(DP(x1,y1,x2,y,no - 1) + s[x1][y + 1][x2][y2],DP(x1,y + 1,x2,y2,no - 1) + s[x1][y1][x2][y])); } return (dp[x1][y1][x2][y2][no] = ans); } int main() { // Read(); int i,j; scanf("%d",&n); int sum = 0; for (i = 1; i <= 8; ++i) { for (j = 1; j <= 8; ++j) { scanf("%d",&mat[i][j]); sum += mat[i][j]; } } CL(s,0); CL(dp,-1); int x1,y1,x2,y2; for (x1 = 1; x1 <= 8; ++x1) { for (y1 = 1; y1 <= 8; ++y1) { for (x2 = x1; x2 <= 8; ++x2) { for (y2 = y1; y2 <= 8; ++y2) { // printf("%d %d %d %d\n",x1,y1,x2,y2); for (i = x1; i <= x2; ++i) { for (j = y1; j <= y2; ++j) { s[x1][y1][x2][y2] += mat[i][j]; } } s[x1][y1][x2][y2] *= s[x1][y1][x2][y2]; dp[x1][y1][x2][y2][1] = s[x1][y1][x2][y2]; } } } } DP(1,1,8,8,n); double ans = (1.0*dp[1][1][8][8][n])/(1.0*n) - (1.0*sum*sum)/(1.0*n*n); printf("%.3f\n",sqrt(ans)); return 0; }