Evolution Game(DAG)

题目描述
In the fantasy world of ICPC there are magical beasts. As they grow, these beasts can change form, and every time they do they become more powerful. A beast cannot change form completely arbitrarily though. In each form a beast has n eyes and k horns, and these affect the changes it can make.

A beast can only change to a form with more horns than it currently has.
A beast can only change to a form that has a difference of at most w eyes. So, if the beast currently has n eyes it can change to a form with eyes in range [n - w, n + w].

A beast has one form for every number of eyes between 1 and N, and these forms will also have an associated number of horns. A beast can be born in any form. The question is, how powerful can one of these beasts become? In other words, how many times can a beast change form before it runs out of possibilities?

输入
The first line contains two integers, N and w, that indicate, respectively, the maximum eye number, and the maximum eye difference allowed in a change (1 ≤ N ≤ 5000; 0 ≤ w ≤ N).
The next line contains N integers which represent the number of horns in each form. I.e. the ith number, h(i), is the number of horns the form with i eyes has (1 ≤ h(i) ≤ 1 000 000).

输出
For each test case, display one line containing the maximum possible number of changes.

样例输入
复制样例数据
5 5
5 3 2 1 4
样例输出
4

提示
Start with 1 horn and 4 eyes, and it can change 4 times: (1 horn 4 eyes) -> (2 horns 3 eyes) -> (3 horns 2 eyes) -> (4 horns 5 eyes) -> (5 horns 1 eye).

怎么说了,DAG现在在我看来就是一个有向无环图,可以转换为DAG上的最长路、最短路、路径计数等问题,首先给你一个嵌套矩形问题,由大到小套,可以有一个最长路径,当然最短路径就是0或者1,所以一个大范围里小范围的求最大最小就是DAG模型,再然后有一个硬币问题,有n种硬币,面值有n种每种有无限多,选几个硬币使得面值之和恰好为S;输出硬币数目的最大值和最小值,本质上也是DAG上的路径问题,将每种面值看做一个点,表示还需要凑足的点,则初始状态为S,目标状态为0,当前状态为i,每使用一个硬币j,状态便转移到i-vj,这个题的起点必须是S,终点必须是0,所以最短路才是有意义的,如何求DAG中不固定的最长路径呢?设d[i]表示从节点i出发的最长路长度,状态转移方程第一步只能走到他的相邻点d(i)=max(d(j)+1),采用记忆化搜索的的方式计算上式。

#include <iostream>
#include <iomanip>
#include <algorithm>
#include <stdlib.h>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <bitset>
#include <stack>
#include <queue>
#include <set>
#include <vector>
#include <map>

using namespace std;
const int INF = 0x3f3f3f3f;
int n,m;
struct node{
    int eye;
    int horn;
    int res;
}arr[5005];

int dp(int i){
    int& ans=arr[i].res;
    if(ans>0)return ans;
    ans=1;
    int e_max=arr[i].eye+m;
    int e_min=arr[i].eye-m;
    for(int j=1;j<=n;j++){
        if((arr[j].horn>arr[i].horn)&&(arr[j].eye>=e_min)&&(arr[j].eye<=e_max))
            ans=max(ans,dp(j)+1);
    }
    return ans;
}

int main(){

    while(cin>>n>>m){
            memset(arr,0,sizeof(arr));
        for(int i=1;i<=n;i++){
            cin>>arr[i].horn;
            arr[i].eye=i;
            arr[i].res=0;
        }
        for(int i=1;i<=n;i++)
            dp(i);
        int maxx=-1;
        for(int i=1;i<=n;i++){
                if(arr[i].res>maxx)
            maxx=arr[i].res;
        }
        cout<<maxx-1<<endl;
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值