題目連接git
複習了下餐巾計劃問題。全忘了=-=網絡
首先這是一道網絡流。而後本題有\(n\)種建圖方法,以及\(smy\) dalao還有單純形作法。
先假設全部物品都是買入的。那麼對於每一天,拆成兩個點\(i,i'\),\(S\to i\)連邊\((1,cost_{a_i})\)(容量\(1\)費用\(cost_{a_i}\)),\(i'\to T\)連邊\((1,0)\),\(i\to i'\)連邊\((1,0)\)。這樣就能知足一些基本要求了。
而後考慮能夠把某個\(a_i\)留到以後一天。考慮從\(i-1\)向\(a_i\)上次出現的位置\(las_{a_i}\)連邊,容量\(1\)費用\(-cost_{a_i}\);\(i\to i+1\)連邊\((k-1,0)\)。\(las_{a_i}\)那一天的流量能夠流到\(i-1\)再流回\(las_{a_i}'\),退回\(cost_{a_i}\)的錢。
邊的含義是,表示容許保留\(k-1\)種物品在架子上(必需要保留當前物品因此是\(k-1\))。當前物品的流量在\(i\)已經有了,因此讓\(a_i\)上次的流量經過\(i-1\)流回去。spa
//31ms 100KB #include <queue> #include <cstdio> #include <cctype> #include <cstring> #include <algorithm> #define S 0 #define gc() getchar() typedef long long LL; const int N=407,M=N*5,INF=0x3f3f3f3f; int Cost,T,A[N],c[N],las[N],H[N],Enum,nxt[M],to[M],cap[M],cost[M],dis[N],cur[N]; bool vis[N]; inline int read() { int now=0;register char c=gc(); for(;!isdigit(c);c=gc()); for(;isdigit(c);now=now*10+c-48,c=gc()); return now; } inline void AE(int u,int v,int w,int c) { to[++Enum]=v, nxt[Enum]=H[u], H[u]=Enum, cap[Enum]=w, cost[Enum]=c; to[++Enum]=u, nxt[Enum]=H[v], H[v]=Enum, cap[Enum]=0, cost[Enum]=-c; } bool SPFA() { static bool inq[N]; static std::queue<int> q; memset(inq,0,T+1), memset(dis,0x3f,T+1<<2); dis[S]=0, q.push(0); while(!q.empty()) { int x=q.front(); q.pop(); inq[x]=0; for(int i=H[x],v; i; i=nxt[i]) if(cap[i]&&dis[v=to[i]]>dis[x]+cost[i]) dis[v]=dis[x]+cost[i], !inq[v]&&(q.push(v),inq[v]=1); } return dis[T]<INF; } bool DFS(int x) { if(x==T) return 1; vis[x]=1; for(int &i=cur[x],v; i; i=nxt[i]) if(!vis[v=to[i]]&&cap[i]&&dis[v]==dis[x]+cost[i]&&DFS(v)) return --cap[i],++cap[i^1],Cost+=cost[i],1; return 0; } int MCMF() { while(SPFA()) { memset(vis,0,T+1), memcpy(cur,H,T+1<<2); while(DFS(S)); } return Cost; } int main() { // freopen("B.in","r",stdin); // freopen("B.out","w",stdout); int n=read(),K=read(); Enum=1, T=n<<1|1; for(int i=1; i<=n; ++i) A[i]=read(); for(int i=1; i<=n; ++i) c[i]=read(); for(int i=1; i<=n; ++i) { AE(S,i,1,c[A[i]]), AE(i,i+n,1,0), AE(i+n,T,1,0); if(i<n&&K>1) AE(i,i+1,K-1,0); if(las[A[i]]) AE(i-1,las[A[i]]+n,1,-c[A[i]]); las[A[i]]=i; } printf("%d\n",MCMF()); return 0; }