令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; }