先给一个Virtual Judge 上挂的地址 dp

A - A Spy in the Metro

题意

起点站和终点站之间有若干个站点,同时,在起点站和终点站会在若干的固定时间始出列车。某人将从起点站出发,在t时到终点站见人,但是希望在站点等尽量少的时间。求出最少的等待时间。

分析

dp。。
“时间 是 一个天然的序”,所以,影响决策的只有时间和当前的站点。
dp[i][j] 表示 在 第i时间 在 j 站点的最小等待时间。所以每一个都面临最多三种的决策:

  • 在原地等待一分钟
  • 选择向左开的列车
  • 选择向右开的列车

    三种决策中选择最小等待时间的。
    考虑边界条件:dp[T][n]= 0, 其他时间的dp[T][i] 预先设成正无穷,在dp过程中无法选择。

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;const int maxn = 50 + 5;
const int maxt = 200 + 5;
const int INF = 1000000000;// has_train[t][i][0]表示时刻t,在车站i是否有往右开的火车
int t[maxn], has_train[maxt][maxn][2];
int dp[maxt][maxn];int main()
{int kase = 0, n, T;while(cin >> n >> T && n){int M1, M2, d;for(int i = 1; i <= n-1; i++) cin >> t[i];// 预处理,计算has_train数组memset(has_train, 0, sizeof(has_train));cin >> M1;while(M1--){cin >> d;for(int j = 1; j <= n-1; j++){if(d <= T) has_train[d][j][0] = 1;d += t[j];}}cin >> M2;while(M2--){cin >> d;for(int j = n-1; j >= 1; j--){if(d <= T) has_train[d][j+1][1] = 1;d += t[j];}}// DP主过程for(int i = 1; i <= n-1; i++) dp[T][i] = INF;dp[T][n] = 0;for(int i = T-1; i >= 0; i--)for(int j = 1; j <= n; j++){dp[i][j] = dp[i+1][j] + 1; // 等待一个单位if(j < n && has_train[i][j][0] && i+t[j] <= T)dp[i][j] = min(dp[i][j], dp[i+t[j]][j+1]); // 右if(j > 1 && has_train[i][j][1] && i+t[j-1] <= T)dp[i][j] = min(dp[i][j], dp[i+t[j-1]][j-1]); // 左}// 输出//cout << dp[0][1] << endl;cout << "Case Number " << ++kase << ": ";if(dp[0][1] >= INF) cout << "impossible\n";else cout << dp[0][1] << "\n";}return 0;
}

后续的题目待续。。

C-Tour

这一道问题有一个十分高大上的问题,叫做 双调旅行商问题。

题意

某人从最左的一点出发,按照严格从左到右的顺序移动到最右一点。然后从最右点返回,按照严格从右到左的顺序回到最左点,并且每一个点都只能访问一次。求最小的距离。

抽象

给你 n 个二维坐标上的点,你需要经过所有的点然后走回原地,求最短路径。

思路

首先,想成是两个人从最左点出发,一同走到最右点,两人中间的访问地点不能相同。可以用dp(i,j),表示1~max{i,j}的点全部走完了,第一个人走到i点,第二个人走到j点,还需要多长的距离。

状态间的转移方式:
为防止dp(i,j) = dp(j,i),对解的产生冲突。
现在同时加上 强制条件:i > j。
原先 可以写成:dp(i,j)= dp(i+1,j)+ dp(i,j+1)。(这是向i+1点转移的方式)
但是 由 j 点转移到 i+1点是不符合条件的,所以先将i,j 对调,再让j点移动到i+1点。于是可以变成 dp(i+1, i);
所以, dp(i,j) = dp(i+1, j) + dp(i+1, i);

边界条件:dp(n-1, j) = dis(n, n-1) + dis(n,j)

代码

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <queue>
#include <stack>
#include <string>
#include <bitset>
#include <cstdio>
#include <limits>
#include <vector>
#include <climits>
#include <cstring>
#include <cstdlib>
#include <fstream>
#include <numeric>
#include <sstream>
#include <iostream>
#include <algorithm>
#define MEM(a,x) memset(a,x,sizeof(a))
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
const int maxn = 1010;
double dp[maxn][maxn];
double dis[maxn][maxn];
struct Point
{int x, y;
};
Point p[maxn];
double dist(Point a, Point b)
{return sqrt((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y));
}
int main()
{//freopen("in.txt","r",stdin);//freopen("out.txt","w",stdout);int n;while(cin >> n){for(int i = 1; i <= n; i++){cin >> p[i].x >> p[i].y;}for(int i = 1; i <= n; i++){for(int j = i+1; j <= n; j++){dis[i][j] = dis[j][i] = dist(p[i], p[j]);}}for(int j = 1; j <= n; j++)dp[n-1][j] = dis[n][n-1] + dis[n][j];for(int i = n-2; i >= 1; i--){for(int j = 1; j <= n; j++){dp[i][j] = min(dp[i+1][j]+dis[i][i+1], dp[i+1][i]+dis[j][i+1]);}}printf("%.2lf\n", dp[1][1]);}return 0;
}

D-单向TSP问题

题意

给出二维数组,从最左一列任意位置出发每次往右、右上或者右下的方向移动,到最后的一列。需要注意的是,第一行的右上为最后一行对应的位置,同理,最后一行的情况相同。
每一个都有三种决策的情况。思路比较简单,关键实现。还有就是要在开一个数组来打印路径。
看代码:

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <queue>
#include <stack>
#include <string>
#include <bitset>
#include <cstdio>
#include <limits>
#include <vector>
#include <climits>
#include <cstring>
#include <cstdlib>
#include <fstream>
#include <numeric>
#include <sstream>
#include <iostream>
#include <algorithm>
#define MEM(a,x) memset(a,x,sizeof(a))
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
const int INF = 999999999;
int a[105][105], dp[105][105], p[105][105];
int main()
{
//    freopen("in.txt","r",stdin);//freopen("out.txt","w",stdout);int n, m;while(cin >> n >> m){for(int i = 0; i < n; i++)for(int j = 0; j < m; j++){cin >> a[i][j];dp[i][j] = INF;}for(int i = 0; i < n; i++)dp[i][m-1] = a[i][m-1];for(int j = m-2; j >=0; j--){for(int i = 0; i < n; i++){int c[] = {i-1, i, i+1};if(i == 0) c[0] = n-1;if(i == n-1) c[2] = 0;sort(c, c+3);
//                for(int k = 1; k < 3; k++)
//                    cout << c[k] << " ";
//                cout << endl;dp[i][j] = INF;for(int k = 0; k < 3; k++){int v = dp[c[k]][j+1] + a[i][j];if(dp[i][j] > v){dp[i][j] = v;p[i][j] = c[k];}}}}
//        for(int i = 0; i < n; i++)
//        {//             for(int j = 0; j < m-1; j++)
//               cout << p[i][j] << " ";
//               cout << endl;
//        }int ans = 999999999;int first = 0;for(int i = 0; i < n; i++){if(ans > dp[i][0]){ans = dp[i][0];first = i;}}printf("%d", first+1);for(int i = p[first][0], j = 1; j < m; i = p[i][j], j++) printf(" %d", i+1);cout << endl << ans << endl;}return 0;
}

F - Lighting System Design

题意

设计一个照明系统,一共有n种灯泡进行选择。不同种类的灯泡必须用不同的电源,但同一种灯泡却可以共用一个电源。每种灯泡给定:电压,电源费用,每个灯泡的费用和所需灯泡数。同时可以把一些灯泡换成电压更高的另一种灯泡来节省电源的费用,计算出最优的花费。

分析

贪心的思考,每种电压的灯泡要换就全换。
先将所用种类的灯泡按照电压值进行从小到大的排序,每种灯泡都是可以将前面的灯泡替换成本身的灯泡,所以可以dp(i) 表示截止到第i种灯泡的最优花费。
dp(i) = min{dp(j) + (j~i num) * price[i] + k [i]} ,同时也可以用前缀数组进行优化。

代码

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <queue>
#include <stack>
#include <string>
#include <bitset>
#include <cstdio>
#include <limits>
#include <vector>
#include <climits>
#include <cstring>
#include <cstdlib>
#include <fstream>
#include <numeric>
#include <sstream>
#include <iostream>
#include <algorithm>
#define MEM(a,x) memset(a,x,sizeof(a))
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
const int maxn = 1005;
const int INF = 1000000000;
struct L
{int v, k, cost, num;
};
L l[maxn];
int dp[maxn], s[maxn];
bool cmp(L a, L b)
{return a.v < b.v;
}
int main()
{
//    freopen("in.txt","r",stdin);//freopen("out.txt","w",stdout);int n;while(cin >> n && n){for(int i = 1; i <= n; i++){cin >> l[i].v >> l[i].k >> l[i].cost >> l[i].num;}sort(l+1, l+n+1, cmp);s[0] = 0;for(int i = 1; i <= n; i++)s[i] = s[i-1] + l[i].num;dp[0] = 0;for(int i = 1; i <= n; i++){dp[i] = s[i] * l[i].cost + l[i].k;for(int j = 0; j < i; j++){int v = dp[j] + (s[i] - s[j])*l[i].cost + l[i].k;dp[i] = min(dp[i], v);}}cout << dp[n] << endl;}return 0;
}

G- Partitioning by Palindromes

题意

输入一个由小写字母组成的字符串,划分成尽量少的回文串。

分析

设dp(i) 表示 0~ i 划分成最小回文串的个数。
状态转移方程为:
dp(i) = min{ dp(j) + 1 | s[j+1…i] 是回文串};
边界: dp(i) = i+1;
在实现的时候,注意对开头就能构成回文串的个数进行特判为1.

代码

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <queue>
#include <stack>
#include <string>
#include <bitset>
#include <cstdio>
#include <limits>
#include <vector>
#include <climits>
#include <cstring>
#include <cstdlib>
#include <fstream>
#include <numeric>
#include <sstream>
#include <iostream>
#include <algorithm>
#define MEM(a,x) memset(a,x,sizeof(a))
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
const int INF = 10000000;
const int maxn = 1000+10;
int p[maxn][maxn], dp[maxn];
string s;
bool is_p(int l, int r)
{while(l <= r){if(s[l] != s[r]) return false;l++;r--;}return true;
}
int main()
{
//    freopen("in.txt","r",stdin);//freopen("out.txt","w",stdout);int t;cin >> t;while(t--){cin >> s;int n = s.size();for(int i = 0; i < n; i++){for(int j = 0; j < n; j++){p[i][j] = is_p(i,j);}}for(int i = 0; i < n; i++) dp[i] = i+1;for(int i = 1; i < n; i++){if(p[0][i]) dp[i] = 1;for(int j = 1; j <= i; j++){if(p[j][i]){
//                    cout << dp[j] << endl;dp[i] = min(dp[i], dp[j-1]+1);}}}cout << dp[n-1] << endl;}return 0;
}

OK。。。

UVA 几道dp题总结相关推荐

  1. UVa在线比赛单题汇总-----DP专题

    动态规划基础 例题 LA 3882 UVa 3882 - And Then There Was One 递推------------无力orz UVa 10635 10635 - Prince and ...

  2. 字节面试必须拿下的十道算法题,你会几道?

    前言 大家好,我是bigsai. 最近不少小伙伴跟我交流刷题肿么刷,我给的建议就是先剑指offer和力扣hot100,在这些题中还有些重要程度和出现频率是非常非常高的,今天给大家分享当今出现频率最高的 ...

  3. 【算法】两道算法题根据提供字母解决解码方法和城市的天际线天际线问题

    算法目录 解码方法 Java解答参考: 天际线问题 Java解答参考: 大家好,我是小冷. 上一篇了解了项目相关的知识点 接下来看下两道算法题吧,用Java解答,可能更能激发一下大脑思考. 解码方法 ...

  4. 杭电46道DP牛人总结

    原文地址:杭电46道DP牛人总结作者:飞泉鸣玉 杭电46道DP牛人总结 HDU 动态规划(46道题目)倾情奉献~ [只提供思路与状态转移方程] 收藏 Robberies http://acm.hdu. ...

  5. 字节跳动-2020秋招-笔试题剖析【5道算法题】

    字节跳动-2020秋招-笔试题剖析[5道算法题],限时120分钟. 让我们一起来看看这些题吧! 题一:模型文件去重 [题目描述] 抖音上不同的用户类型我们有不同的用户模型文件. 我们有一个模型配置文件 ...

  6. 杭电60道DP问题总结(一)

    杭电60道DP问题总结: DP是一个很有艺术的思想.看似简单的背后却隐藏着深刻的含义. 题目连接地址:http://acm.hdu.edu.cn/problemclass.php?id=516& ...

  7. ❤️手撕这十道HiveSQL题还不能吊打面试官,却能保你不被吊打❤️【推荐收藏】

    全网最详细的大数据Hive文章系列,强烈建议收藏加关注! 新文章都已经列出历史文章目录,帮助大家回顾前面的知识重点. 目录 系列历史文章 前言 HiveSQL十题 第一题 1.需求 2.数据准备 3. ...

  8. Re: 求助:5道算法题

    http://www.newsmth.net/frames.html 发信人: cutepig (cutepig), 信区: Algorithm 标  题: 求助:5道算法题 发信站: 水木社区 (S ...

  9. BAT七年经验,却抵不过外企面试的两道算法题?

    整理| 琥珀 出品| AI科技大本营 又遇年底跳槽季,如果你曾在 BAT 等互联网大厂有过较为丰富的工作经验,想要换份工作,面试时会主要考虑哪些因素? 面试外企,却被两道算法题难住? 近日,一位网友在 ...

最新文章

  1. 计算机书籍- 聊天机器人技术原理与应用
  2. 通过正则表达式验证日期
  3. Light Head R-CNN论文笔记
  4. LeetCode 2050. 并行课程 III(拓扑排序)
  5. aop注解配置切点 spring_Spring通过自定义注解灵活配置AOP切点
  6. 算法:阶乘的五种算法
  7. linux 0.11 返回用户侧,iPhone 11 11 Pro 用户必备教程:重启手机,恢复模式,DFU模式...
  8. java读取配置文件properties_让我来告诉你Spring框架是怎么样通过properties来获得对象的?...
  9. 红帽linux中文系统下载iso,红帽子9.0版下载-redhat linux 9.0 iso下载 简体中文正式版-IT猫扑网...
  10. 计算机键盘上范的怎么点击,微信怎么用键盘最小化 电脑最小化键盘怎么按
  11. 2022智源大会议程公开 | 探索智能的原理,构建脑科学与AI的桥梁
  12. 日记2021/9/28
  13. 【鼠标事件 MouseEvent】clientX clientY offsetX offsetX pageX screenX screenY
  14. opencv 泊松融合
  15. linux系统与window区别,Linux和windows操作系统有哪些区别
  16. MATLAB画路径图(带结点,不同颜色的路径)
  17. MEMS传感器的6大种类简介-传感器专题
  18. 码分多址matlab代码,基于matlab的码分多址系统仿真
  19. Java学习打卡第八天——[Collection终结之HashMap,Collections的简介和使用]
  20. Tensorflow安装过程的一些问题及解决办法

热门文章

  1. 搭建DNF台服之服务器篇
  2. 用jupyter notebook卸载Python第三方库
  3. 图像处理--gamma矫正/Python
  4. 阅文集团以人民币10.8亿元出售懒人听书股权给腾讯音乐
  5. python写矩阵奇异值分解
  6. PostMessaget与ON_MESSAGE
  7. Micro(二)[环境搭建]
  8. linux vi或者vim编辑器中如何显示行号
  9. opencv 凸包convexHull、道格拉斯-普克算法Douglas-Peucker algorithm、approxPloyDP 函数
  10. Android事件分发机制在实战开发中的应用之二