1 条题解
-
0
自动搬运
来自洛谷,原作者为

奇米
**搬运于
2025-08-24 22:22:21,当前版本为作者最后更新于2020-06-15 09:38:02,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
题解 - 甜梦
题目意思
-
一道很神仙的状压
-
我们发现,我们自然而然地想到了状压。于是表示在状态下较小的点为的最大快乐值。这个东西其实是对这段区间的二进制表示。
-
我们如何用较小标号去推出较大标号,我们首先说出结论。其中为状态下最高位的位置。具体是因为我们的是走不了回头路的,所以一定是当前状态下的最高位。这个还是可以理解的吧。
-
接下来我们来看转移,其实莫过于种情况。
-
同时移动到
- 那么转移:
- 这个好理解就是两个点并到一个点,然后更新状态为
-
移动到,不动
-
那么转移:$f_{S|(1<<P-u),u}=\max(f_{S|(1<<P-u),u},f_{S,u}+val_P$
-
这个不需要考虑以前状态是否出现过,因为编号是递增的
-
-
移动到,不动
-
如果此时那么成为较小点,于是$f_{(S>>v-u)|(1<
>v-u)|(1<<P-v),v},f_{S,u}+val_{P})$ -
此时这个要看在上一个状态中是否出现过
-
如果此时那么还是较小点,于是$f_{S>>P-u|1,u}=\max(f_{S>>P-u|1,u},f_{S,u}+val_{P})$
-
此时这个要看在上一个状态中是否出现过
-
-
于是答案就是。就是两个点都在点,其他就是写细节问题啦~~~
#include <bits/stdc++.h> #define For(i,a,b) for ( int i=(a);i<=(b);i++ ) #define Dow(i,b,a) for ( int i=(b);i>=(a);i-- ) #define GO(i,x) for ( int i=head[x];i;i=e[i].nex ) #define mem(x,s) memset(x,s,sizeof(x)) #define cpy(x,s) memcpy(x,s,sizeof(x)) #define YES return puts("YES"),0 #define NO return puts("NO"),0 #define GG return puts("-1"),0 #define pb push_back using namespace std; inline int read() { int sum=0,ff=1; char ch=getchar(); while(!isdigit(ch)) { if(ch=='-') ff=-1; ch=getchar(); } while(isdigit(ch)) sum=sum*10+(ch^48),ch=getchar(); return sum*ff; } const int mod=1e9+7; const int mo=998244353; const int N=5005; const int M=1<<13|1; int n,m,l,val[N],a[N][N],f[N][M],High[M]; vector<int> G[N]; int main() { n=read();m=read();l=read(); For(i,1,n) val[i]=read(); For(i,1,m) { int x,y; x=read(),y=read(); if(!a[x][y]) a[x][y]=1,G[x].pb(y); } For(S,0,(1<<l+1)-1) for ( int j=l+1;~j;j-- ) if((S>>j)&1) { High[S]=j; break; } memset(f,-1,sizeof(f)); For(i,1,n) { if(f[i][1]==-1) f[i][1]=0; For(S,0,(1<<l+1)-1) { if(!(S&1)) continue; int idv=i+High[S]; if(f[i][S]==-1) continue; For(j,0,(int)G[idv].size()-1) { int v=G[idv][j]; if(a[i][v]) f[v][1]=max(f[i][S]+val[v],f[v][1]); if(v-i>l) continue; int nxt=S|(1<<v-i); f[i][nxt]=max(f[i][nxt],f[i][S]+val[v]); } For(j,0,(int)G[i].size()-1) { int v=G[i][j]; if(v-idv>l) continue;//1: if(v>idv) { int nxt=(S>>idv-i)|(1<<v-idv); if(S>>v-i&1) f[idv][nxt]=max(f[idv][nxt],f[i][S]); else f[idv][nxt]=max(f[idv][nxt],f[i][S]+val[v]); } else { int nxt=S>>v-i|1; if(S>>v-i&1) f[v][nxt]=max(f[v][nxt],f[i][S]); else f[v][nxt]=max(f[v][nxt],f[i][S]+val[v]); } } } } printf("%d\n",f[n][1]); return 0; } -
- 1
信息
- ID
- 5526
- 时间
- 1000~3000ms
- 内存
- 256MiB
- 难度
- 6
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者