条件DP UVA 672 Gangsters

题目传送门

题意:n个歹徒进饭店,可变化宽度的门,范围[0, k],每个歹徒进门在ti时间进门,身材si,进去后有pi的成功值,问最大的成功值

分析:首先按照进门时间排序,dp[i][j] 表示第i个歹徒在门大小为j的时候进门的最大成功值,那么状态转移方程:dp[i][j] = dp[i-1][k] + a[i].p 条件是门大小从k到j的时间差小于i和ii-1人进门时间差

收获:这类有条件限制的dp转移,我分类为条件DP

代码:

/************************************************
* Author        :Running_Time
* Created Time  :2015-8-31 16:19:35
* File Name     :UVA_672.cpp
 ************************************************/

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <sstream>
#include <cstring>
#include <cmath>
#include <string>
#include <vector>
#include <queue>
#include <deque>
#include <stack>
#include <list>
#include <map>
#include <set>
#include <bitset>
#include <cstdlib>
#include <ctime>
using namespace std;

#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
typedef long long ll;
const int N = 1e2 + 10;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
struct People   {
    int t, p, s;
    bool operator < (const People &r) const {
        return t < r.t;
    }
}a[N];
int dp[N][N];

int main(void)    {
    int T;  scanf ("%d", &T);
    while (T--) {
        int n, door, time;  scanf ("%d%d%d", &n, &door, &time);
        for (int i=1; i<=n; ++i)    scanf ("%d", &a[i].t);
        for (int i=1; i<=n; ++i)    scanf ("%d", &a[i].p);
        for (int i=1; i<=n; ++i)    scanf ("%d", &a[i].s);
        sort (a+1, a+1+n);

        memset (dp, -1, sizeof (dp));
        int ans = 0;    dp[0][0] = 0;
        for (int i=1; i<=n; ++i)    {
            for (int j=0; j<=door; ++j) {
                for (int k=0; k<=door; ++k) {
                    if (dp[i-1][k] == -1 || abs (j - k) > a[i].t - a[i-1].t)   continue;
                    if (a[i].s == j && j)   {
                        dp[i][j] = max (dp[i][j], dp[i-1][k] + a[i].p);
                    }
                    else    {
                        dp[i][j] = max (dp[i][j], dp[i-1][k]);
                    }
                    ans = max (ans, dp[i][j]);
                }
            }
        }
        printf ("%d\n", ans);
        if (T)  puts ("");
    }

    return 0;
}

  

时间: 2024-10-01 01:26:46

条件DP UVA 672 Gangsters的相关文章

状压DP UVA 11795 Mega Man&#39;s Mission

题目传送门 1 /* 2 题意:洛克人有武器可以消灭机器人,还可以从被摧毁的机器人手里得到武器,问消灭全部机器人的顺序总数 3 状态压缩DP:看到数据只有16,就应该想到状压(并没有).因为是照解题报告写的,代码里加点注释,省的以后忘记了 4 */ 5 /************************************************ 6 * Author :Running_Time 7 * Created Time :2015-8-8 10:41:28 8 * File Nam

状压DP UVA 10817 Headmaster&#39;s Headache

题目传送门 1 /* 2 题意:学校有在任的老师和应聘的老师,选择一些应聘老师,使得每门科目至少两个老师教,问最少花费多少 3 状压DP:一看到数据那么小,肯定是状压了.这个状态不好想,dp[s1][s2]表示s1二进制表示下至少有1位老师的科目集合 4 s2表示至少有2位老师的科目集合所花费的最小金额,状态转移方程(01):dp[t1][t2]=min(dp[t1][t2],dp[j][k]+c[i]); 5 j,k为当前两个集合,t1,t2为转移后的集合,另外求t1,t2用到了& |位运算

uva 672(dp)

题意:有n个歹徒要进入一家餐厅,餐厅有一扇门,门初始大小是0,门会每秒增大1或减小1或不变,但范围在[0,k],然后每个歹徒都有到达餐厅的时间ti,每个人有一个财富值pi和自己的体型值si,只有歹徒到达餐厅时门的大小和si相等时他才能进入餐厅,餐厅就会增加pi,问餐厅最多增加的总pi值是多少. 题解:f[i]表示前i个人能让餐厅增加的总Pi值是多少,先把歹徒到餐厅的时间排序,然后对比歹徒间到达时间差和体型差来判断如果前者进入后者是否也能进入,f[i] = max(f[i], f[j] + pi)

(DP) UVA 10003

F - Cutting Sticks Time Limit:3000MS     Memory Limit:0KB     64bit IO Format:%lld & %llu Submit Status Practice UVA 10003 Appoint description:  System Crawler  (2015-01-31) Description  Cutting Sticks  You have to cut a wood stick into pieces. The m

区间DP UVA 1351 String Compression

题目传送门 1 /* 2 题意:给一个字符串,连续相同的段落可以合并,gogogo->3(go),问最小表示的长度 3 区间DP:dp[i][j]表示[i,j]的区间最小表示长度,那么dp[i][j] = min (dp[j][k] + dp[k+1][i+j-1]), 4 digit (i / k) + dp[j][j+k-1] + 2)后者表示可以压缩成k长度连续相同的字符串 4.5 详细解释 5 */ 6 /*****************************************

递推DP UVA 1366 Martian Mining

题目传送门 1 /* 2 题意:抽象一点就是给两个矩阵,重叠的(就是两者选择其一),两种铺路:从右到左和从下到上,中途不能转弯, 3 到达边界后把沿途路上的权值相加求和使最大 4 DP:这是道递推题,首先我题目看了老半天,看懂后写出前缀和又不知道该如何定义状态好,写不出状态转移方程,太弱了. 5 dp[i][j]表示以(i, j)为右下角时求得的最大值,状态转移方程:dp[i][j] = max (dp[i-1][j] + sum1[i][j], dp[i][j-1] + sum2[i][j])

递推DP UVA 1291 Dance Dance Revolution

题目传送门 1 /* 2 题意:给一串跳舞的动作,至少一只脚落到指定的位置,不同的走法有不同的体力消耗,问最小体力消费多少 3 DP:dp[i][j][k] 表示前i个动作,当前状态(j, k)的最小消费,状态转移方程:(a[i], k) <- min (a[i-1], k) + cost 4 以及(a[i-1], a[i]) <- min (a[i-1], k) + cost, (k, a[i])和(a[i], a[i-1])情况类似,最后再去最小值就行了 5 */ 6 /*********

多维DP UVA 11552 Fewest Flop

题目传送门 1 /* 2 题意:将子符串分成k组,每组的字符顺序任意,问改变后的字符串最少有多少块 3 三维DP:可以知道,每一组的最少块是确定的,问题就在于组与组之间可能会合并块,总块数会-1. 4 dp[i][j]表示第i组以第j个字符结尾的最少块数,状态转移方程:dp[i][j] = min (dp[i][j], dp[i-1][l] + chunk - 1); 5 意思就是枚举上一组的所有字符,当出现在i组并且不是放到末尾,那么能-1 6 */ 7 /******************

区间DP UVA 11584 Partitioning by Palindromes

题目传送门 1 /* 2 题意:给一个字符串,划分成尽量少的回文串 3 区间DP:状态转移方程:dp[i] = min (dp[i], dp[j-1] + 1); dp[i] 表示前i个字符划分的最少回文串, 4 如果s[j] 到 s[i]是回文串,那么可以从dp[j-1] + 1递推过来 5 */ 6 #include <cstdio> 7 #include <cstring> 8 #include <algorithm> 9 #include <cmath&g