UVA 10037 Bridge (基础DP)

题意:

  过河模型:有n个人要渡河,每个人渡河所耗时可能不同,只有1只船且只能2人/船,船速取决于速度慢的人。问最少耗时多少才能都渡完河?

思路:

  n<2的情况比较简单。

  考虑n>2的情况,第一次肯定是两个耗时少的先过去。接下来有两种渡河方式,有可能是{a回,另外2人去,b回,a和b去},也可能是{a回,a和另一人去}。也就是说a和b的协作可以送走其他2个人,或者是a自己当船夫,送走另外一个人。这样子就有两种决策啦。

  先将他们排个序(升序),然后a和b先过去。如果还有人没有过河,若left>=2时,可以选择第一种渡河方式,也可以选择第二种。当left==1就只能选择第二种了。然后转移行了。dp[i]表示送走[1->i]的所有人的花费。

  1 #include <bits/stdc++.h>
  2 #include <iostream>
  3 #include <cstdio>
  4 #include <cstring>
  5 #include <cmath>
  6 #include <map>
  7 #include <algorithm>
  8 #include <vector>
  9 #include <iostream>
 10 #define pii pair<int,int>
 11 #define INF 0x7f7f7f7f
 12 #define LL unsigned long long
 13 using namespace std;
 14 const double PI  = acos(-1.0);
 15 const int N=50100;
 16 int dp[N], path[N];
 17 deque<int> que;
 18 vector<int> vect,ans[N];
 19 int cal(int n)
 20 {
 21     sort(vect.begin(), vect.end());
 22
 23     int a=vect[0];
 24     if(n==1)
 25     {
 26         printf("%d\n", a );
 27         printf("%d\n", a );
 28         return 0;
 29     }
 30     int b=vect[1];
 31     if( n==2 )
 32     {
 33         printf("%d\n", b );
 34         printf("%d %d\n", a, b );
 35         return 0;
 36     }
 37     //DP******************
 38     dp[1]=b;
 39     path[1]=2;
 40     for(int i=2; i<vect.size(); i++)
 41     {
 42         int t1=a+vect[i];
 43         if(dp[i]>dp[i-1]+t1)        //送1个
 44         {
 45             dp[i]= dp[i-1]+t1 ;
 46             path[i]=1;
 47         }
 48
 49         if( i+1==vect.size() )  continue;   //最后1个了
 50         int t2=a+b*2+vect[i+1];
 51         if(dp[i+1]>dp[i-1]+t2 )        //送2个
 52         {
 53             dp[i+1]=dp[i-1]+t2;
 54             path[i+1]=2;
 55         }
 56     }
 57     que.clear();    //寻找路径
 58     int t=n-1;
 59     while(t>0)
 60     {
 61         if(path[t]==1)    que.push_front(1);
 62         else              que.push_front(2);
 63         t-=path[t];
 64     }
 65     //输出*********************************
 66     printf("%d\n", dp[n-1]);
 67     printf("%d %d\n", a, b);    //第一步必定是a和b先过去
 68     que.pop_front();
 69     int cnt=1;
 70     while(!que.empty())
 71     {
 72         t=que.front();        que.pop_front();
 73         cnt+=t;
 74         if(t==1)
 75         {
 76             printf("%d\n", a);
 77             printf("%d %d\n", a, vect[cnt]);
 78         }
 79         if(t==2)
 80         {
 81             printf("%d\n", a);
 82             printf("%d %d\n", vect[cnt-1], vect[cnt]);
 83             printf("%d\n", b);
 84             printf("%d %d\n", a, b);
 85         }
 86     }
 87 }
 88
 89
 90 int main()
 91 {
 92     freopen("input.txt", "r", stdin);
 93     int t, n, a;
 94     cin>>t;
 95     while(t--)
 96     {
 97         vect.clear();
 98         for(int i=0; i<N; i++)    ans[i].clear();
 99         memset(dp, 0x7f, sizeof(dp));
100         memset(path, 0, sizeof(path));
101
102
103         scanf("%d",&n);
104         for(int i=1; i<=n; i++)
105         {
106             scanf("%d", &a);
107             vect.push_back(a);
108         }
109         cal(n);
110         if(t)   puts("");
111     }
112 }

AC代码

时间: 2024-10-13 19:08:24

UVA 10037 Bridge (基础DP)的相关文章

UVa 10037 - Bridge

题目大意 在一个晚上有N个人过河,他们有一个手电筒,需要有手电筒才能过河,每次最多两个人同时过河,每次过河时间等于速度最慢的那个人的过河时间,让所有人全部过河,花费的时间最少是多少? 分析 如果只有一个人过河,那么过河的总时间就是这个人过河的时间.如果是两个人过河,那么总时间为过河速度较慢的那个人的过河时间.如果是三个人过河,总花费时间为a+b+c.当人数大于等于4时,我们每次都让两个速度最慢的人过河,假设A和B表示速度最快和第二快的人,速度分别为a,b,C和D表示速度最慢和第二慢的人,速度分别

UVA - 10037 Bridge 贪心

题目大意:有n个人要过桥,每次只能过去两个,且这两个人中至少有一个人要带手电筒,但手电筒只有一个. 每个人都有一个过桥时间,两个人的过桥时间取决于时间长的那个. 问所有人都过桥需要多少时间,怎么过桥 解题思路:贪心,因为所有人都要过桥,且手电筒只有一个,所以要过桥时间短的人把手电筒拿回来. 有两种过桥方式使过桥时间达到最短,假设t1,t2(t1 <= t2)是当前过桥时间最短的两个人,tm,tn是过桥时间最长的两个人,且(tm <= tn) 第一种过桥方式:(不考虑最后一次t1和t2一起过桥)

训练指南 UVA - 10917(最短路Dijkstra + 基础DP)

layout: post title: 训练指南 UVA - 10917(最短路Dijkstra + 基础DP) author: "luowentaoaa" catalog: true mathjax: true tags: - 最短路 - 基础DP - Dijkstra - 图论 - 训练指南 Walk Through the Forest UVA - 10917 题意 Jimmy打算每天沿着一条不同的路走,而且,他只能沿着满足如下条件的道路(A,B):存在一条从B出发回家的路径,比

UVa 116 Unidirectional TSP(DP)

题意  一个n*m的环形矩阵(第一行和最后一行是相邻的)  从第一列任意位置出发  只能往右上,右,右下3个方向走  求走到第m列经过的的最小数字和 基础DP  横着的数塔问题 #include <bits/stdc++.h> #define l(x) d[x][j+1] using namespace std; const int N = 105; int n, m, g[N][N], d[N][N], fol[N][N]; int main() { int n, m, u, b, t, k

基础dp

队友的建议,让我去学一学kuangbin的基础dp,在这里小小的整理总结一下吧. 首先我感觉自己还远远不够称为一个dp选手,一是这些题目还远不够,二是定义状态的经验不足.不过这些题目让我在一定程度上加深了对dp的理解,但要想搞好dp,还需要多多练习啊. HDU - 1024 开场高能 给出一个数列,分成m段,求这m段的和的最大值,dp[i][j]表示遍历到第i个数,已经划分了j段,对于每一个数有两种决策,加入上一个区间段,自己成为一个区间段,故dp[i][j] = max(dp[i-1][j]+

[UVA 12589]Learning Vector[DP]

题目链接:[UVA 12589]Learning Vector[DP] 题意分析:给出n个矢量,从中选择k个,以坐标原点为起点,收尾相连,问:这样的k个周围相连矢量与x轴围成图形的最大面积的两倍是多少? 解题思路:考虑状态:dp[id][pick][h]代表到第id个矢量为止,选择pick个矢量离最大面积还差多少,h为当前图形最右端高度.具体转移看代码. 这里着重说一下为什么要对这些矢量按斜率进行排序: 首先,整个求解过程其实就是在暴力枚举这些向量的组合,只不过采用了记忆化搜索优化. 其次,对于

UVA 1356 - Bridge(自适应辛普森)

UVA 1356 - Bridge 题目链接 题意:一个桥长为B,桥上建电线杆,杆高为H,两杆之间距离不超过D,电线杆总长为L,杆子都是等距的,现在建最少的电线杆,问这时候电线离地面高度是多少 思路:二分高度,求出电线长,判断长度够不够即可,那么问题就变成怎么求弧长 求弧长公式为∫w/201+(f′(x)2)??????????√, 建立坐标系使得f(x)=ax2,带入点(w/2, h)求出a,得到方程 那么问题就变成怎么求这个积分了 利用辛普森自适应法,去求即可 代码: #include <c

Uva 12018 Juice Extractor dp

题目链接:点击打开链接 题意: 切水果游戏 给出n个水果 水果出现在屏幕上的时间的区间 1.每次切会把屏幕上所有水果切完 2.当同时切3个或以上时计分,分数为切的水果个数 3.不能遗漏水果 问最高得分 dp[i] 表示 最后一次切第i个的得分. #include<stdio.h> #include<algorithm> #include<string.h> #include<iostream> using namespace std; #define N 1

POJ 3616 Milking Time 基础DP

Milking Time Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 5743   Accepted: 2401 Description Bessie is such a hard-working cow. In fact, she is so focused on maximizing her productivity that she decides to schedule her next N (1 ≤ N ≤