$n leq 1e8$个石头,$x leq 8$个蝌蚪一开始在最左边$x$个石子,要跳到最右的$x$个,每次只能最左边的蝌蚪跳一次,一个石头不能站两个蝌蚪,跳可以跳$1到k,x leq k leq 8$步,跳$i$步的代价是$cost_i$,还有$q leq 25$个神奇石头,跳上去代价会$+w_i$,$w_i$可能为负数。问完成跳跃的最小代价。
不知道跳蝌蚪是什么操作只听过跳蛤,大概是变相膜?
好的严肃。从小数字$x$和$k$入手。由于每次只有最左的蝌蚪会跳,所以这$x$个蝌蚪一定每时每刻都在某连续的$k$个石头上。记这$k$个石头最左的那个(不一定上面有蝌蚪)为$i$,那么$i$处右边$k$个石子上的蝌蚪状态可以用二进制表示,最多是$C_8^4=70$个状态,挺小。这样就可以做转移了,转移复杂度是$C_k^x*k$,再乘个$n$直接爆炸。不过我们来看这个转移,$dp(i,j)=dp(i-1,k)+cost_t$,想到啥了?走若干步的最短路!这是可以用矩乘优化的,于是在不考虑$q$时,可以做$log_2n*(C_k^x)^3$的$dp$。
然后来看$q$。一块神奇石头影响了$k$块地(di)的(de)转移,因此最多会有$q*k$块地受影响,挺小,矩乘到这些地段时停住,暴力转移。最终复杂度$log_2n*(C_k^x)^3+qk^2C_k^x$。
1 //#include<iostream> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cstdio> 5 //#include<map> 6 #include<math.h> 7 //#include<time.h> 8 //#include<complex> 9 #include<algorithm> 10 using namespace std; 11 12 int X,K,n,m,q; 13 #define LL long long 14 const LL inf=1e18; 15 struct Mat 16 { 17 LL a[73][73]; 18 Mat() {for (int i=1;i<=70;i++) for (int j=1;j<=70;j++) a[i][j]=inf;} 19 Mat operator * (const Mat &b) 20 { 21 Mat ans; 22 for (int k=1;k<=m;k++) 23 for (int i=1;i<=m;i++) 24 for (int j=1;j<=m;j++) 25 ans.a[i][j]=min(ans.a[i][j],a[i][k]+b.a[k][j]); 26 return ans; 27 } 28 }base,f; 29 30 Mat pow(Mat a,int b) 31 { 32 Mat ans,tmp=a; for (int i=1;i<=m;i++) ans.a[i][i]=0; 33 while (b) 34 { 35 if (b&1) ans=ans*tmp; 36 tmp=tmp*tmp; b>>=1; 37 } 38 return ans; 39 } 40 41 int state[266],ls,who[73]; 42 struct Ran{int l,r;}qq[33],ran[33]; int len; 43 LL g[73],h[73];int cost[12]; 44 struct Block{int pos,w;}ww[33]; 45 bool cmpww(const Block &a,const Block &b) {return a.pos<b.pos;} 46 struct Hash 47 { 48 int first[107],le; struct Edge{int to,v,next;}edge[33]; 49 Hash() {le=2;} 50 void insert(int x,int y) {int h=x%107; Edge &e=edge[le]; e.to=x; e.v=y; e.next=first[h]; first[h]=le++;} 51 int find(int x) {int h=x%107; for (int i=first[h];i;i=edge[i].next) if (edge[i].to==x) return edge[i].v; return -2e9;} 52 }ha; 53 54 int main() 55 { 56 scanf("%d%d%d%d",&X,&K,&n,&q); 57 for (int i=1;i<=K;i++) scanf("%d",&cost[i]); 58 for (int i=1;i<=q;i++) scanf("%d%d",&ww[i].pos,&ww[i].w); sort(ww+1,ww+1+q,cmpww); 59 LL ans=0; for (int &i=q;i;i--) if (ww[i].pos>=n-X+1) ans+=ww[i].w; else break; 60 for (int i=1;i<=q;i++) ha.insert(ww[i].pos,ww[i].w); 61 for (int i=1;i<=q;i++) qq[i].l=max(ww[i].pos-K,2),qq[i].r=ww[i].pos; 62 len=0; for (int i=1;i<=q;i++) 63 { 64 if (len && qq[i].l<=ran[len].r+1) ran[len].r=qq[i].r; 65 else len++,ran[len].l=qq[i].l,ran[len].r=qq[i].r; 66 } 67 ls=0; for (int i=1;i<(1<<K);i++) 68 { 69 int cnt=0; 70 for (int j=0;j<K;j++) if ((i>>j)&1) cnt++; 71 if (cnt==X) ls++,state[i]=ls,who[ls]=i; 72 } m=ls; 73 for (int i=1;i<=ls;i++) 74 { 75 int s=who[i]>>1; 76 if ((who[i]&1)==0) base.a[i][state[s]]=0; 77 else for (int j=1;j<=K;j++) if (((s>>(j-1))&1)==0) base.a[i][state[s|(1<<(j-1))]]=cost[j]; 78 } 79 f.a[1][1]=0; ran[0].r=1; 80 for (int i=1;i<=len;i++) 81 { 82 f=f*pow(base,ran[i].l-ran[i-1].r-1); 83 for (int j=1;j<=ls;j++) g[j]=f.a[1][j]; 84 for (int j=ran[i].l;j<=ran[i].r;j++) 85 { 86 for (int k=1;k<=ls;k++) h[k]=inf; 87 for (int k=1;k<=ls;k++) 88 { 89 int s=who[k]>>1; 90 if ((who[k]&1)==0) h[state[s]]=min(h[state[s]],g[k]); 91 else for (int l=1,tmp;l<=K;l++) if (((s>>(l-1))&1)==0) 92 { 93 int ns=s|(1<<(l-1)); 94 if ((tmp=ha.find(j+l-1))!=-2e9) h[state[ns]]=min(h[state[ns]],g[k]+cost[l]+tmp); 95 else h[state[ns]]=min(h[state[ns]],g[k]+cost[l]); 96 } 97 } 98 for (int k=1;k<=ls;k++) g[k]=h[k]; 99 } 100 for (int j=1;j<=ls;j++) f.a[1][j]=g[j]; 101 } 102 f=f*pow(base,n-X+1-ran[len].r); 103 printf("%lld ",ans+f.a[1][1]); 104 return 0; 105 }