黑书上的DP例题

pagesectionnotitlesubmit
1131.5.1例题1括号序列POJ1141
1161.5.1例题2棋盘分割POJ1191
1171.5.1例题3决斗Sicily1822
1171.5.1例题4“舞蹈家”怀特先生ACM-ICPC Live Archive
1191.5.1例题5积木游戏http://202.120.80.191/problem.php?problemid=1244
1231.5.2例题1方块消除http://poj.org/problem?id=1390
1231.5.2例题2公路巡逻http://202.120.80.191/problem.php?problemid=1600
1251.5.2例题3并行期望值POJ1074
1311.5.2例题6不可分解的编码http://acmicpc-live-archive.uva.es/nuevoportal/data/problem.php?p=2475
1331.5.2例题7青蛙的烦恼http://codewaysky.sinaapp.com/problem.php?id=1014
1351.5.2例题9最优排序二叉树http://judge.noi.cn/problem?id=1059
1381.5.2例题10Bugs公司POJ1038
1391.5.2例题11迷宫统计http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=70&page=show_problem&problem=1472
1421.5.2例题12贪吃的九头龙http://judge.noi.cn/problem?id=1043
1511.5.3问题2最长上升子序列问题http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=17&page=show_problem&problem=1475
1511.5.3问题3最优二分检索树http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=15&page=show_problem&problem=1245
1521.5.3问题4任务调度问题POJ1180
1211.5.11.5.8艺术馆的火灾http://221.192.240.23:9088/showproblem?problem_id=1366
1441.5.21.5.10快乐的蜜月http://judge.noi.cn/problem?id=1052
1451.5.21.5.12佳佳的筷子http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=14&page=show_problem&problem=1212
1461.5.21.5.13偷懒的工人POJ1337
1461.5.21.5.15平板涂色POJ1691
1471.5.21.5.16道路重建POJ1947
1471.5.21.5.17圆和多边形http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1679
1481.5.21.5.18Jimmy落地POJ1661
1481.5.21.5.19免费糖果http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=13&page=show_problem&problem=1059
1571.5.31.5.22回文词POJ1159
1571.5.31.5.24邮局POJ1160
1581.5.31.5.26奶牛转圈POJ1946
1581.5.31.5.27元件折叠http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=14&page=show_problem&problem=1180

现在开始训练一下DP:

递归动机的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]来的。所以,我们要另开一个二维数组记录每种最优状态的来源点。然后再递归的输出即可。

View Code
#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 115using 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,所以最大值取大一点。这里让哥条了很长时间。。

View Code
#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 10using 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;
}

 

 sicily 1822 Fight Club

题意:黑书

思路:

开始吧题意理解错了,一位如果判断i必须从i开始一次与i + 1,i +2比较呢。SB了。。

dp[i][j]表示i能否与j相遇,记住这里是相遇不表示i与j谁能打败谁。如果判断x点,我们把x点查分为x与n + 1,这样讲原来的环转化成连,然后求x与n +1是否能够相遇即可

dp[i][j] = (dp[i][k] && dp[k][j] && (mat[i][k],mat[j][k])),mat[i][j]表示i能否打败j

View Code
#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 50using namespace std;const int inf = 0x7f7f7f7f;
const int mod = 1000000007;int mat[N][N];int dp[N][N];
int seq[N];
bool vt[N][N];int n;
int DP(int l,int r)
{int k;if (vt[l][r]) return dp[l][r];for (k = l + 1; k <= r - 1; ++k){dp[l][r] = (DP(l,k)&&DP(k,r)&&(mat[seq[l]][seq[k]] || mat[seq[r]][seq[k]]));if (dp[l][r]) break;}vt[l][r] = true;return dp[l][r];
}
int main()
{
//    Read();int T,i,j;scanf("%d",&T);while (T--){scanf("%d",&n);CL(mat,0);for (i = 1; i <= n; ++i)for (j = 1; j <= n; ++j)scanf("%d",&mat[i][j]);for (i = 1; i <= n; ++i){CL(dp,0); CL(vt,false);int pos = (i - 1);if (pos == 0) pos = n;int ln = 0;for (j = i; j <= n; ++j) seq[++ln] = j;for (j = 1; j <= i - 1; ++j) seq[++ln] = j;seq[++ln] = n + 1;for (j = 1; j <= n; ++j){dp[j][j + 1] = dp[j + 1][j] = 1;vt[j][j + 1] = vt[j + 1][j] = true;}DP(1,ln);if (dp[1][ln]) printf("1\n");else printf("0\n");}
//        if (T != 0)printf("\n");}return 0;
}

 

hdu 3632 A Captivating Match

题意:

这题和上题目意思一样,只不过这里是序列1-n然后每个人可以选择左右两边的人进行对决,我刚开始看到这题目的时候,就以为是上边那道题目,结果样例过了,就是不对。

思路:
这里某个人i如果能够胜出,那么他一定能够和0点并且和n + 1点相遇。(与上题一样,抽象出来的两个点)。然后我们只要枚举任意两点是否能够相遇即可,

dp[i][j] = (dp[i][k] && dp[k][j] && (mat[i][k],mat[j][k])),mat[i][j]表示i能否打败j,   这里根据i到j的距离进行递推的。

View Code
#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 30007
#define N 117using namespace std;const int inf = 100000007;
const int mod = 1000000007;int val[N];
int mat[N][N];
int n;
int dp[N][N];
bool vt[N][N];bool isok(int i,int j,int k)
{if (dp[i][k] && dp[k][j] && (mat[i][k] || mat[j][k])) return true;else return false;
}
int main()
{
//    Read();int T,i,j;int cas = 1;scanf("%d",&T);while (T--){scanf("%d",&n);for (i = 1; i <= n; ++i) scanf("%d",&val[i]);CL(mat,0);//记住要初始化for (i = 1; i <= n; ++i)for (j = 1; j <= n; ++j) scanf("%d",&mat[i][j]);CL(dp,0);for (i = 0; i <= n + 1; ++i) dp[i][i + 1] = dp[i + 1][i] = 1;int k,p;for (k = 2; k <= n; ++k)//递推策略
        {for (i = 0; i + k <= n + 1; ++i){j = i + k;for (p = i + 1; p <= j - 1; ++p){if (isok(i,j,p)){dp[i][j] = 1;}}}}int ans = 0;for (i = 1; i <= n; ++i){if (dp[0][i] && dp[i][n + 1] && val[i] > ans) ans = val[i]; //i能否杀到0并且能够杀到n + 1
        }printf("Case %d: %d\n",cas++,ans);}return 0;
}

 

pku 1390 Blocks

题意:看给书吧..

思路:

我们考虑的是最后一段是单独消去还是和前边的一起消去,这样就可以构造出递归的递推式了。

题目的方块可以表示称color[i],len[i],1<=i<=l
这里l表示有多少"段"不同的颜色方块
color[i]表示第i段的颜色,len[i]表示第i段的方块长度
让f[i,j,k]表示把(color[i],len[i]),(color[i+1],len[i+1]),...,(color[j-1],len[j-1]),(color[j],len[j]+k)合并的最大得分
考虑(color[j],len[j]+k)这一段,要不马上消掉,要不和前面的若干段一起消掉
1.如果马上消掉,就是f[i,j-1,0]+(len[j]+k)^2
2.如果和前面的若干段一起消,可以假设这"若干段"中最后一段是p,则此时的得分是f[i,p,k+len[j]]+f[p+1,j-1,0]
于是f[i,j,k] = max{ f[i,j-1,0]+(len[j]+k)^2, f[i,p,k+len[j]]+f[p+1,j-1,0] 

View Code
#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>
#include <utility>#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 long long
#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 207using namespace std;const int inf = 0x7f7fffff;
const ll mod = 1000000007;int dp[N][N][N];
int a[N],of[N],b[N];
int n,ln;int q_DP(int l,int r,int k)
{int p;if (dp[l][r][k] != 0) return dp[l][r][k];if (l == r){return (dp[l][r][k] = (b[r] + k)*(b[r] + k));}int ans = 0;ans = max(ans,q_DP(l,r - 1,0) + (b[r] + k)*(b[r] + k));for (p = l; p + 1 <= r - 1; ++p){if (of[r] == of[p])ans = max(ans,q_DP(l,p,k + b[r]) + q_DP(p + 1,r - 1,0));}return dp[l][r][k] = ans;
}
int main()
{
//    Read();int i;int T,cas = 1;scanf("%d",&T);while (T--){scanf("%d",&n);ln = 0; CL(a,0);for (i = 0; i < n; ++i){scanf("%d",&a[i]);}ln = 0; int ct = 0;for (i = 0; i < n; ++i){if (a[i] != a[i + 1]){b[++ln] = ct + 1;of[ln] = a[i];ct = 0;}else ct++;}
//        b[++ln] = ct;
//        of[ln] = a[n - 1];CL(dp,0);q_DP(1,ln,0);printf("Case %d: %d\n",cas++,dp[1][ln][0]);}return 0;
}

 

 

 

 

 多决策动机的DP:

https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=32

题意:黑书。。

思路:
这里每一步要么走左腿,要么走右腿,要么原地不动。DFS求解肯定超时,因为状态数太多,所以我们只好利用DP记录所有状态,然后通过每一步的决策。求解所有满足条件的状态。

View Code
#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 10017using namespace std;const int inf = 0x7f7fffff;
const int mod = 1000000007;int a[N];
int dp[5][5][3];int getS(int x,int y)
{if (x == 0) return 2;else if (x == y) return 1;else if (abs(x - y) == 2) return 4;else return 3;
}
int main()
{
//    Read();int i,j,k;int n;a[0] = 0;while (~scanf("%d",&a[1])){if (a[1] == 0) break;i = 2;while (scanf("%d",&a[i])){if (a[i] == 0) break;i++;}n = i - 1;for (i = 0; i <= 4; ++i){for (j = 0; j <= 4; ++j){for (k = 0; k <= 1; ++k)dp[i][j][k] = inf;}}dp[0][0][0] = 0;int u = 0, v = 1;for (k = 0; k < n; ++k){for (i = 0; i <= 4; ++i){for (j = 0; j <= 4; ++j){if (dp[i][j][u] != inf){if (a[k + 1] != j) //保证左右脚不能在一起dp[a[k + 1]][j][v] = min(dp[a[k + 1]][j][v],dp[i][j][u] + getS(i,a[k + 1]));if (i != a[k + 1])dp[i][a[k + 1]][v] = min(dp[i][a[k + 1]][v],dp[i][j][u] + getS(j,a[k + 1]));}}}swap(u,v); //滚动数组优化for (i = 0; i <= 4; ++i){for (j = 0; j <= 4; ++j){dp[i][j][v] = inf;}}}int ans = inf;for (i = 0; i <= 4; ++i){if (i != a[n])ans = min(dp[i][a[n]][u],ans);}for (j = 0; j <= 4; ++j){if (j != a[n])ans = min(dp[a[n]][j][u],ans);}printf("%d\n",ans);}return 0;
}

 

积木游戏

题意:。。。

思路:
就是按着黑书上的第一种思路做的,这里有个地方卡了一下, 就是j表示的类成了j堆,在枚举的时候不能只到m-1否则最后累到第m的堆的最后一个也就不存在了,。

View Code
#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>
#include <utility>#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 long long
#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 107using namespace std;const int inf = 0x7f7fffff;
const ll mod = 1000000007;int dp[N][N][N][4];
bool vt[N][N][N][4];
int a[N][4][4];
int n,m;bool over(int i,int x,int j,int y)
{int sda = max(a[i][x][0],a[i][x][1]);int sdb = min(a[i][x][0],a[i][x][1]);int pda = max(a[j][y][0],a[j][y][1]);int pdb = min(a[j][y][0],a[j][y][1]);if (sda <= pda && sdb <= pdb) return true;else return false;
}
int main()
{
//    Read();int i,j,k,p,q;int x,y,z;scanf("%d%d",&n,&m);CL(a,0);for (i = 1; i <= n; ++i){scanf("%d%d%d",&x,&y,&z);//表示第i个面的的长宽高a[i][0][0] = x; a[i][0][1] = y; a[i][0][2] = z;a[i][1][0] = y; a[i][1][1] = z; a[i][1][2] = x;a[i][2][0] = z; a[i][2][1] = x; a[i][2][2] = y;}CL(dp,0); CL(vt,false);vt[0][0][0][0] = true;for (i = 0; i < n; ++i){for (j = 0; j <= min(i,m); ++j){for (k = 0; k <= i; ++k){for (p = 0; p < 3; ++p){if (vt[i][j][k][p]){for (q = 0; q < 3; ++q){//可以累加if (over(i + 1,q,k,p)){dp[i + 1][j][i + 1][q] = max(dp[i + 1][j][i + 1][q],dp[i][j][k][p] + a[i + 1][q][2]);vt[i + 1][j][i + 1][q] = true;}//另起一堆dp[i + 1][j + 1][i + 1][q] = max(dp[i + 1][j + 1][i + 1][q],dp[i][j][k][p] + a[i + 1][q][2]);vt[i + 1][j + 1][i + 1][q] = true;//直接跳过dp[i + 1][j][k][p] = max(dp[i + 1][j][k][p],dp[i][j][k][p]);vt[i + 1][j][k][p] = true;
//                            printf(">>>>%d %d %d\n",dp[i + 1][j][i + 1][q],dp[i + 1][j + 1][i + 1][q],dp[i + 1][j][k][p]);
                        }}}}}}int ans = 0;
//    printf("%d %d\n",n,m);for (k = 1; k <= n; ++k){for (p = 0; p < 3; ++p){
//            printf(">>>>>>%d\n",dp[n][m][k][p]);ans = max(ans,dp[n][m][k][p]);}}printf("%d\n",ans);return 0;
}

 

 公路巡逻

思路:

dp[i][j]表示到达在时间为j时第i个关口与巡逻车相遇的最少次数 dp[i + 1][j + 1] = max(dp[i + 1][j + 1],dp[i][j] + s); s表示目标车在 [j, j + k]时间段内从第i个关口出发到i + 1个关口与巡逻车相遇的次数。

其实状态转移很好想,只是在车辆相遇上脑子短路了,我们只要排除不相遇的就好了。

这里还没有优化。。

View Code
#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 long long
#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", "r", stdin)
#define Write() freopen("dout", "w", stdout);#define M 86405
#define N 55using namespace std;const int inf = 0x7f7f7f7f;
const int mod = 1000000007;struct node
{int s,e;
}nd[N][N];
int ln[N];int dp[N][M];
bool vt[N][M];
int n,m;int main()
{
//    Read();int i,j,k;int ni,di;char ti[7];scanf("%d%d",&n,&m);CL(ln,0);CL(nd,0);for (j = 0; j < m; ++j){scanf("%d%s%d",&ni,ti,&di);int no = 0;   int sum = 0;for (i = 0; i < 6; ++i){if (i%2 == 1){no = no*10 + ti[i] - '0';int tmp = 0;if (i == 1) tmp = 3600;else if (i == 3) tmp = 60;else tmp = 1;sum += no*tmp;no = 0;}else{no = no*10 + ti[i] - '0';}}int &p = ln[ni];nd[ni][p].s = sum;nd[ni][p].e = sum + di;p++;}for (i = 1; i <= n; ++i){for (j = 0; j <= 86400; ++j){dp[i][j] = inf;}}CL(vt,false); dp[1][21600] = 0;vt[1][21600] = true;for (i = 1; i < n; ++i){for (j = 21600; j <= 51000; ++j){if (vt[i][j]){for (k = 300; k <= 600; ++k){int s = 0;int p;for (p = 0; p < ln[i]; ++p){if (nd[i][p].e == j + k) s++;else{if (j <= nd[i][p].s && j + k <= nd[i][p].e) continue;if (j >= nd[i][p].s && j + k >= nd[i][p].e) continue;s++;}}dp[i + 1][j + k] = min(dp[i + 1][j + k],dp[i][j] + s);vt[i + 1][j + k] = true;}}}}int ans = inf;int tim = 0;for (i = 21600; i <= 51000; ++i){if (vt[n][i] && dp[n][i] < ans){ans = dp[n][i];tim = i;}}int hh = tim/3600;tim -= hh*3600;int mm = tim/60;tim -= mm*60;int ss = tim;printf("%d\n%02d%02d%02d\n",ans,hh,mm,ss);return 0;
}

 

 ===================================================================

 

poj 1337 A Lazy Worker

题意:

一个懒工人,他想工作的时间尽量少。有N个任务,每个任务有开始时间和deadline,工人完成这个工作需要ti时间。如果某个时刻有工作可以做(这里是说,如果从这个时刻开始某个工作,在deadline之前能够完成),那么这个工人必须做,但是如果这个时刻存在着多余1件工作可以做,工人可以选择;假设这个时刻没有工作可以做了,工人就可以偷懒直到有新的任务到来

思路:

刚开始以为只要我一空下来有工作,我就必须从这一点开始工作来着,其实不是的,只要在最晚期限之前完成该工作即可。

dp[i]表示在时间点i时,完成工作所需要的最少时间,dp[i + 1] = min(dp[i + 1],dp[i])当该时间没有工作干时,当有多个工作时,dp[i + tk] = min(dp[i + tk],dp[i] + tk) k表示第k个工作可以再时间点i完成

这里注意inf = 0x3fffffff 因为会有inf的相加,这里快整死我了,给很长时间没有条出来。。

View Code
#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>
#include <list>#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 long long
#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 107
#define N 117
using namespace std;const ll mod = 1000000007;
const int inf = 0x3fffffff;struct node
{int ti,ai,di;
}nd[N];int dp[260];
vector<int> work[260];int main()
{
//    Read();
//    printf("%d \n%d\n",0x7fffffff,0x3fffffff);int T;int i,j;int n;scanf("%d",&T);while (T--){scanf("%d",&n);int s = inf, e = 0;for (i = 0; i < n; ++i){scanf("%d%d%d",&nd[i].ti,&nd[i].ai,&nd[i].di);s = min(s,nd[i].ai); e = max(e,nd[i].di);}for (i = s; i <= e; ++i){work[i].clear();for (j = 0; j < n; ++j){if (i >= nd[j].ai && i + nd[j].ti <= nd[j].di){work[i].push_back(j);}}}for (i = s; i <= e; ++i) dp[i] = inf;dp[s] = 0;for (i = s; i < e; ++i){if (work[i].size() == 0) dp[i + 1] = min(dp[i + 1],dp[i]);else{int sz = work[i].size();for (int j = 0; j < sz; ++j){int k = work[i][j];dp[i + nd[k].ti] = min(dp[i + nd[k].ti],dp[i] + nd[k].ti);}}}printf("%d\n",dp[e]);}return 0;
}

 

 

 

 

转载于:https://www.cnblogs.com/E-star/archive/2013/04/15/3022391.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/274289.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

静态创意和动态创意_我在22岁时学到的关于创意指导的知识

静态创意和动态创意During my last semester at college, I took a course titled “Collaborative Workshop”. The entire course focused on how to best collaborate within a team setting. We were placed into groups of 4 or 5. These were our “creative director” …

vim7.1在windows下的编码设置[转]

在gvm配置文件中&#xff1a; &#xff08;gvim安装目录下的_vimrc文件中&#xff09; """""""""""""""""""""""""""""&…

绝对编码和增量编码_用户体验设计师应该学习编码吗? 绝对

绝对编码和增量编码Even though I was trained as a graphic designer, I’ve never limited myself to that field exclusively. My particular interest in how things work didn’t allow me to stand still and as a young kid, I was already pulling apart all my toys t…

两个ID

在itpub上注册了ID googlgoracle &#xff0c;发过不少的求助帖子。 http://www.itpub.net/home.php?modspace&dothread&viewme 在CSDN 上ID:googlg,注册时间挺早的2008年&#xff0c;一直也没有弄过。 http://write.blog.csdn.net/postlist http://blog.csdn.net/goo…

完美主义怎么解决_相信我,你不要完美主义

完美主义怎么解决Perfectionism to UXers is like a badge of honour. We pride ourselves on the attention to detail and the drive to constantly push our work to the next level. When I asked some of my clients who share this sentiment about perfectionism, they …

MDK linker和debug的设置以及在RAM中调试

有误或者表述不清楚请指出&#xff0c;谢谢 硬件&#xff1a;TQ2440开发板、jlink V8 固件 软件&#xff1a;J-LINK ARM 4.08i、MDK4.20 先解释下MDK中三种linker之间的区别 设置集中在option linker选项卡 1.采用Target对话框中的ram和rom地址。采用此方式&#xff0c;…

FS_S5PC100 UBOOT-2011.12移植,支持DM9000

在uboot中已经支持了DM9000驱动代码在drivers/net/目录下的dm9000x.c dm9000x.h 修改include/configs/smdkc100.h 文件&#xff0c;注释掉SMC911X的支持&#xff0c;添加对DM9000的支持//#define CONFIG_SMC911X 1 /* we have a SMC9115 on-board *///#define…

为什么ui框架设计成单线程_评估UI设计的备忘单

为什么ui框架设计成单线程Whether you’re evaluating your design proposals or giving feedback to a colleague during a design critique or an informal conversation, you may find this actionable cheat sheet valuable. It’s quick to digest and its questions are …

css 菜单栏悬停_在CSS中构建悬停菜单

css 菜单栏悬停A good menu design is an important part of any website or web app UI. Using only modern HTML and CSS, all kinds of menu combinations can be created to handle whatever user interactions are necessary. In this article, we’ll take a look at how…

一级学科和二级学科_在多学科团队中工作的6个障碍(以及如何解决这些问题)

一级学科和二级学科In a team with different skillsets, one can be hopeful and idealistic about the outcome. The goal is to work as one team, put users first and create awesome experiences. Unfortunately, things don’t always go as planned.在一支具有不同技能…

LBS核心技术解析(引子)

http://www.cnblogs.com/LBSer/archive/2013/04/25/3048754.html 引子&#xff1a; 人们常用“上知天文&#xff0c;下知地理”来形容一个人的博学&#xff0c;人们总是用三要素论“什么时间、什么地点&#xff0c;发生或干了什么事情”来描述一件事情,人们也常常借用“天时、地…

lynda ux_如何建立内部UX团队

lynda uxWritten by Cassandra Naji由卡珊德拉纳吉 ( Cassandra Naji)撰写 The needs of real users are increasingly driving enterprise software design and development. Since 2013, IBM has hired close to 1500 designers and UXers, establishing the largest design…

IE6下div宽高设置

IE6下宽高设置。IE下div 中没有内容时&#xff0c;设置宽高不起作用&#xff0c;必须设置div背景色&#xff0c;并使用滤镜。才能使Div填充目标区域。多用于&#xff0c;其他容器元素使用背景图片&#xff0c;但是背景图片的部分需要其他的事件支持。如跳转。可以使用放置div的…

财务软件开发_财务独立对软件开发人员的重要性

财务软件开发If you read this post, chances that you are a software developer who is seeking financial advice for smart money-saving or investment or early retirement.如果您阅读此文章&#xff0c;则您很可能是一名软件开发人员&#xff0c;正在为精明的省钱或投资…

WIP模块常用表结构

WIP模块常用表结构表名: wip.wip_accounting_classes说明: 离散作业会计科目CLASS_CODE VARCHAR2(10) 帐目ORGANIZATION_ID NUMBER 组织代码CLASS_TYPE NUMBER 帐目类型DESCRIPTION VARCHAR2(240) 描述…

book电子书数据库设计_如何为杀手book的封面设计写出完美的摘要

book电子书数据库设计逐步出版真正的假人 (BOOK PUBLISHING STEP BY STEP FOR REAL DUMMIES) I have spent 18 years in advertising, briefing designers and art directors on various projects — from the simplest typo-only banners to the most complex integrated camp…

5g的负面影响_设计系统的实施是否会对早期概念产生负面影响?

5g的负面影响Athe financial institution where I was recently working the design system was maintained in Sketch libraries and code. A small team working across multiple brands means there is always a question for why we may or may not maintain something. We…

每日英语:Five Really Dumb Money Moves You've Got to Avoid

You know the smartest things to do with your money. But what are the worst moves? What should you avoid?Weirdly enough, they are things that a surprising number of people are still doing─even though they probably know, in their heart of hearts, how fool…

像素/厘米与像素/英寸区别_像素/体素艺术入门指南

像素/厘米与像素/英寸区别Here’s some resources I’ve found helpful so you can start learning pixel or voxel art (as a continuation of this post on 3D resources). Feel free to mention anything I missed in the comments!这是我发现有帮助的一些资源&#xff0c;因…

畅通工程续 最短路

某省自从实行了很多年的畅通工程计划后&#xff0c;终于修建了很多路。不过路多了也不好&#xff0c;每次要从一个城镇到另一个城镇时&#xff0c;都有许多种道路方案可以选择&#xff0c;而某些方案要比另一些方案行走的距离要短很多。这让行人很困扰。现在&#xff0c;已知起…