黑书上的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,一经查实,立即删除!

相关文章

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;…

LBS核心技术解析(引子)

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

Vim中数字自增、自减

&#xff08;1&#xff09;ctrl a&#xff1a;数字自动增加1 按下ctrl a&#xff1a; &#xff08;2&#xff09;number ctrl a&#xff1a;数字自动增加number 例子&#xff1a;想将20修改成100&#xff0c;按下80 ctrl a&#xff1a; &#xff08;3&#xff09;ctrl x…

开源服务器Tornado的初步了解

文章结束给大家来个程序员笑话&#xff1a;[M] 明天看了下Python的一个新web框架&#xff0c;由Facebook开源。不得不说&#xff0c;品牌效应啊&#xff0c;只要是Facebook开源的目项&#xff0c;没有不好用的。Tornado可以说是好用到了极致&#xff0c;从开打官方面页开始懂得…

多线程的那群“象”

最初学习多线程的时候&#xff0c;只学了用Thread这个类&#xff0c;记忆中也用过Mutex&#xff0c;到后来只记得Thread的使用&#xff0c;其余的都忘了。知道前不久写那个Socket连接池时遇到了一些对象如&#xff1a;Semaphore&#xff0c;Interlocked&#xff0c;Mutex等&…

优秀HTML5网站学习范例:从“饥饿游戏浏览器”谈用户体验

继影片《饥饿游戏》获得票房成功后&#xff0c;《饥饿游戏2&#xff1a;火星燎原》也于2012年宣布开拍&#xff0c;将在今年的11月22日登陆全球各大院线。值此之际&#xff0c;微软携手美国狮门影业公司和 RED Interactive Agency 一起为影迷打造了一个基于 HTML5 现代网页规范…

[开源]jquery.ellipsis根据宽度(不是字数)进行内容截断,支持多行内容

jquery.ellipsis 自动计算内容宽度&#xff08;不是字数&#xff09;截断&#xff0c;并加上省略号&#xff0c;内容不受中英文或符号限制。 如果根据字数来计算的话&#xff0c;因为不同字符的宽度并不相同&#xff0c;比如l和W&#xff0c;特别是中英文&#xff0c;最终内容宽…

不安装游戏apk直接启动法

原文地址&#xff1a;http://blog.zhourunsheng.com/2011/09/%E6%8E%A2%E7%A7%98%E8%85%BE%E8%AE%AFandroid%E6%89%8B%E6%9C%BA%E6%B8%B8%E6%88%8F%E5%B9%B3%E5%8F%B0%E4%B9%8B%E4%B8%8D%E5%AE%89%E8%A3%85%E6%B8%B8%E6%88%8Fapk%E7%9B%B4%E6%8E%A5%E5%90%AF%E5%8A%A8%E6%B3%95…

Android客户端打包方案分享

基本介绍 Android应用的自动化打包是应用持续集成以及多渠道发布的基础。当前Android客户端自动化打包的主要有两种方式&#xff0c;Ant和Maven。两种方式本质上都是调用Android SDK里面提供的工具&#xff0c;不过各自有各自的特点。 1. Ant脚本 好处&#xff1a;开发成本较低…

您的UX库不只是书籍

hp ux 密码不过期Looking back on past self, one thing I wish I’d realised is the importance of keeping notes of everything.回顾过去的自我&#xff0c;我希望我意识到的一件事是记录所有事情的重要性。 This means everything interesting I’ve read and written; e…

交互设计精髓_设计空间的精髓

交互设计精髓重点 (Top highlight)什么是空间&#xff1f; (What is Space?) Space is the dimension of height, depth and width within which all things exist and move. Space or Empty space or White space or Negative space are alias given to describe intensional…

ux和ui_UI和UX设计人员的47个关键课程

ux和ui重点 (Top highlight)This is a mega-list of the most critical knowledge for UI, UX, interaction, or product designers at any level.这是所有级别的UI&#xff0c;UX&#xff0c;交互或产品设计人员最关键的知识的大清单。 Many of these lessons are also appli…

深入理解Java内存模型(七)——总结

处理器内存模型 顺序一致性内存模型是一个理论参考模型&#xff0c;JMM和处理器内存模型在设计时通常会把顺序一致性内存模型作为参照。JMM和处理器内存模型在设计时会对顺序一致性模型做一些放松&#xff0c;因为如果完全按照顺序一致性模型来实现处理器和JMM&#xff0c;那么…

沉浸式ui设计_有助于沉浸的视频游戏UI —武器轮

沉浸式ui设计Many action-adventure games rely on the feeling of thrills via bullets, fire, grenade, more bullets, and gigantic booms. The way to enable all these is to offer a massive arsenal, from machetes to assault rifles all the way till bazookas.许多动…

ux设计师薪水_客户现在也是UX设计师

ux设计师薪水Some of you probably know by now, I’m not too fond of the monster the UX industry has become. It’s overblown, overcomplicated and often dishonest towards the clients. It’s also in itself undefined. (where is the E in Experience?)你们中的某些…

分步表单_角色创建分步指南

分步表单The first thing most of us designers are taught is the concept of personas and the necessity of them when it comes to UX and product design. However, knowing is different from applying and it can be difficult to know where to begin when we’re aske…

svg配合css3动画_带有Adobe Illustrator,HTML和CSS的任何网站的SVG动画

svg配合css3动画A top trend in web design for 2020 is the increased use of SVG animations on web pages and in logo design. In this article, we will implement a simple and straight forward method to create relatively complex animation. We will use Adobe Illu…

基于pt100温度计仿真_基于8pt网格的设计系统

基于pt100温度计仿真重点 (Top highlight)This article is the 2nd in a two part series — to the previous chapter in which I demonstrate how to establish an 8pt grid.本文是该系列文章的第二部分 &#xff0c;这是上一章 的第二部分 &#xff0c;在上一章中&#xff0…

利用 k8s 建立软件商店_为企业建立应用商店

利用 k8s 建立软件商店It’s June 2019. I’m sitting in a conference room in Research Triangle Park in North Carolina. At the end of the table are the two executives that have been tapped to lead a new endeavor on behalf of IBM’s $34 billion acquisition of …

苹果复兴_类型复兴的故事:来自Type West的经验教训

苹果复兴Last Fall, I began the 去年秋天&#xff0c;我开始 在旧金山的Type West program at the Letterform档案库中Letterform Archive in San Francisco. For those of you who don’t know, the Letterform Archive is creative heaven — a type nerd’s letter art co…