Timus 1741

令res[i][0]表示升级到i并且是正版的最小消费,res[i][1]表示升级到i并且是盗版的最小消费。

res[i][0]=min(res[i][0],res[k][0]+edge(k,i)) (其中k必须可以升级到i,并且保证升级到i是正版);

res[i][1]=min(res[i][1],res[k][x]+edge(k,i)) (其中res[k][x]表示正版盗版都行,关键保证升级到i是盗版)

简单DP不用再说了,不过就是用到临界表来存储边,减小空间复杂度(姑且这样说)。

#include<iostream>

#include<cstdio>

#include<cstring>

using namespace std;

#define lld __int64

#define MAX 0xffffffffff

struct node

{

    int i,cost,next;

    char state;

}edge[10001];

lld dp[10001][2];

int head[10001],N;

int add(int s,int t,int w,char c)

{

    edge[N].i=t;

    edge[N].cost=w;

    edge[N].state=c;

    edge[N].next=head[s];

    return N++;

}

lld min(lld a,lld b)

{

    return a < b ? a : b;

}

int work(int n,int m)

{

    int i,j,k;

    for(i=1;i<=n;i++) dp[i][0]=dp[i][1]=MAX;

    dp[1][0]=dp[1][1]=0;

    for(i=2;i<=n;i++)

    {

        for(j=head[i];j;j=edge[j].next)

        {

            k=edge[j].i;

            if(dp[k][0]<MAX && (edge[j].state=='L'||edge[j].state=='C'))

            {

                dp[i][0]=min(dp[i][0],dp[k][0]+edge[j].cost);

            }

            if(dp[k][0]<MAX && edge[j].state=='P')

            {

                dp[i][1]=min(dp[i][1],dp[k][0]+edge[j].cost);

            }

            if(dp[k][1]<MAX && (edge[j].state=='C' || edge[j].state=='P'))

            {

                dp[i][1]=min(dp[i][1],dp[k][1]+edge[j].cost);

            }

        }

    }

    return 0;

}

int main()

{

    int i,m,n,s,t,w;

    char str[10];

    while(scanf("%d %d",&n,&m)!=EOF)

    {

        N=1;

        memset(head,0,sizeof(head));

        for(i=0;i<m;i++)

        {

            scanf("%d %d %d %s",&s,&t,&w,str);

            head[t]=add(t,s,w,str[0]);

        }

        work(n,m);

        if(dp[n][0] < MAX || dp[n][1] < MAX)

        {

            printf("Online\n%I64d\n",min(dp[n][0],dp[n][1]));

        }

        else

        {

            printf("Offline\n");

        }

    }

    return 0;

}

你可能感兴趣的:(IM)