[AIZU 2266]Cache Strategy(最大權區間選擇)
阿新 • • 發佈:2018-12-16
/* AIZU 2266 最小花費=最大節省 考慮可以節省M-1個球的花費。 s-1: (M-1,0) i-i+1: (inf,0) a[i]=a[j]時: i-(j-1): (1,-w[a[i]]) // 全部箱子分成M-1個不動的箱子和一個動的箱子 連到j-1並不意味著到j的時候完全取出,而是挪到了可以動的箱子, 這樣子不動的箱子就可以留給j-1秒可能加入的不動點。 如果i-j連的話,如果在第j-1秒加入一個長時間不動的球那就會把他加入可動的箱子裡。 1 2 3 1 2 3 M=2 如果1 4 連, 3 5 連那麼1 3不能共存這樣子不對的。 1 3連,2 4連,3 5連, 3秒時1 3 可以共存在不同屬性箱子中。 動 不動 花費 add1 1 10 2 2 1 20 3 1 3 30 1 1 3 2 2 3 20 3 2 3 */ #include <iostream> #include <vector> #include <queue> #include <algorithm> #include <cstdio> #include <cstring> using namespace std; const int inf = 1<<30; const int mmax = 20000020; const int nmax = 11100; int N,M,K; int w[nmax],a[nmax]; int nex[nmax]; struct Edge{int u,v,cap,cost,nex;}; Edge e[mmax]; int etot=0; int head[nmax]; int dist[nmax],inq[nmax],pre[nmax],e_used[nmax]; //pre:最短路前向點 e_used:到i點前一個用過的邊 int max_flow,min_cost=0; void init(); void addedge(int u,int v,int cap,int cost); bool spfa(int s,int t); void flow_change(int s,int t); void mincost_maxflow(int s,int t); int main(){ int x,tot=0; scanf("%d%d%d",&M,&N,&K); for(int i=1;i<=N;i++){ scanf("%d",&w[i]); } init(); for(int i=1;i<=K;i++){ scanf("%d",&a[i]); } K=unique(a+1,a+1+K)-a-1; memset(nex,-1,sizeof(nex)); addedge(0,1,M-1,0); for(int i=1;i<=K;i++){ tot+=w[a[i]]; if(nex[a[i]]!=-1) addedge(nex[a[i]],i-1,1,-w[a[i]]); nex[a[i]]=i; addedge(i,i+1,inf,0); } mincost_maxflow(0,K); printf("%d\n",tot+min_cost); return 0; } void init(){ max_flow=min_cost=0; etot=1; memset(head,-1,sizeof(head)); } void addedge(int u,int v,int cap,int cost){ //printf("%d %d %d %d\n",u,v,cap,cost); e[++etot].u=u; e[etot].v=v; e[etot].cap=cap; e[etot].cost=cost; e[etot].nex=head[u]; head[u]=etot; e[++etot].u=v; e[etot].v=u; e[etot].cap=0; e[etot].cost=-cost; e[etot].nex=head[v]; head[v]=etot; } bool spfa(int s,int t){ for(int i=s;i<=t;i++)dist[i]=inf; memset(inq,0,sizeof(inq)); memset(pre,-1,sizeof(pre)); queue<int> q; dist[s]=0; q.push(s); inq[s]=1; while(!q.empty()){ int u=q.front(); q.pop(); inq[u]=0; for(int i=head[u];i!=-1;i=e[i].nex){ int v=e[i].v; if(e[i].cap>0&&dist[v]>dist[u]+e[i].cost){ dist[v] = dist[u]+e[i].cost; pre[v] = u; e_used[v] = i; if(!inq[v]){ inq[v] = 1; q.push(v); } } } } return pre[t]!=-1; } void flow_change(int s,int t){ int u,f=inf; for(u=t; u!=s; u=pre[u]){ f=min(f,e[e_used[u]].cap); } max_flow+=f; for(u=t; u!=s; u=pre[u]){ e[e_used[u]].cap -= f; e[e_used[u]^1].cap += f; min_cost += f*e[e_used[u]].cost; } } void mincost_maxflow(int s,int t){ while(spfa(s,t)){ flow_change(s,t); } }