#include<cstdio> #define il inline usingnamespace std;
int n,ans; structquan { int t,p; }q[100001]; int sze;
il intread() { int res=0,sign=1; char c; while ((c=getchar())<'0'||c>'9') if (c=='-') sign=-1; res=c-'0'; while ((c=getchar())>='0'&&c<='9') res=res*10+c-'0'; return res*sign; }
intmain() { freopen("transfer.in","r",stdin); freopen("transfer.out","w",stdout); n=read(); int i,j,g,opt,p,t; for (i=1; i<=n; i++) { opt=read(),p=read(),t=read(); if (opt==0) ans+=p,q[++sze]=(quan){t,p}; else { g=0; for (j=1; j<=sze; j++) { if (t-q[j].t<=45&&q[j].p>=p) { g=j; break; } } if (g==0) ans+=p; else { for (j=g+1; j<=sze; j++) { q[j-1]=q[j]; } sze--; } } g=0; for (j=1; j<=sze; j++) { if (t-q[j].t>45) g++; } for (j=g+1; j<=sze; j++) { q[j-g]=q[j]; } sze-=g; } printf("%d",ans); return0; }
T3 纪念品(souvenir)
10pt
直接输出 m 即可(笑)。
复杂度是 O(1) 的。
30pt
暴力搜索即可(这题暴力比正解还难写,本人现在还是不会写这题暴力)。
复杂度是 O(玄学) 的(笑)。
45pt
考虑 N=1 的部分分。
考虑贪心,如果今天买进的东西明天卖出可以赚钱,就花所有的前来买,这显然是无误的。
复杂度是 O(T) 的。
60pt
考虑 T=2 的部分分。
这是藏的比较深的背包。
因为不管第一天买多少,第二天都要卖掉,那么其实就是以 m 为背包体积,第 i 号物品的体积是 P1,i ,价值是 P2,i−P1,i ,每个物品都有无限个,求最大价值。
#include<cstdio> #include<algorithm> #define il inline usingnamespace std;
int t,n,m; int p[101][101]; int mm,f[1100001];
il intread() { int res=0,sign=1; char c; while ((c=getchar())<'0'||c>'9') if (c=='-') sign=-1; res=c-'0'; while ((c=getchar())>='0'&&c<='9') res=res*10+c-'0'; return res*sign; }
intmain() { freopen("souvenir.in","r",stdin); freopen("souvenir.out","w",stdout); t=read(),n=read(),m=read(); int T,i,j; for (i=1; i<=t; i++) { for (j=1; j<=n; j++) { p[i][j]=read(); } } for (T=2; T<=t; T++) { for (i=0; i<=m; i++) { f[i]=0; } for (i=1; i<=n; i++) { for (j=p[T-1][i]; j<=m; j++) { f[j]=max(f[j],f[j-p[T-1][i]]+p[T][i]-p[T-1][i]); } } mm=0; for (i=0; i<=m; i++) { mm=max(mm,f[i]); } m+=mm; } printf("%d",m); return0; }
T4 加工零件(work)
20pt
直接看第 a 号节点与第 1 号节点有没边相连就行了。
如果是用链式前向星,复杂度是 O(nq) 的;如果是用领接矩阵,复杂度是 O(q) 的。
40pt
BFS 预处理,从第 1 节点出发,看看走 L 不可不可以到第 a 号节点,之后直接离线就好了。
复杂度是 O(玄学+q) 的。
60pt&80pt
本人还没有比较好的做法。。。。。。
100pt
有一个十分显然的结论:设 disi,0/1 分别为第 1 号节点到第 i 号节点的偶数最短路和奇数最短路。
若 L≥disa,Lmod2 的话,那么是可以的。
这是为什么呢?假设 L=disa,Lmod2+2x 那么我们可以先走最短路到 a ,接着再随便选择一条与 a 相连的边,来往 x 次即可。
#include<cstdio> #include<queue> #define il inline usingnamespace std;
int n,m,q; structEdge { int to,next; }edge[200001]; int head[100001],sze; int dis[100001][2];
il intread() { int res=0,sign=1; char c; while ((c=getchar())<'0'||c>'9') if (c=='-') sign=-1; res=c-'0'; while ((c=getchar())>='0'&&c<='9') res=res*10+c-'0'; return res*sign; }
il voidadd(int u,int v) { edge[++sze]=(Edge){v,head[u]}, head[u]=sze; }
il voidbfs() { queue<pair<int,int> > q; int i; q.push(make_pair(1,0)); while (!q.empty()) { int u=q.front().first,l=q.front().second; q.pop(); for (i=head[u]; i; i=edge[i].next) { int v=edge[i].to; if (dis[v][l^1]==1e9) dis[v][l^1]=dis[u][l]+1,q.push(make_pair(v,l^1)); } } }
intmain() { freopen("work.in","r",stdin); freopen("work.out","w",stdout); n=read(),m=read(),q=read(); int i,u,v; for (i=1; i<=m; i++) { u=read(),v=read(); add(u,v),add(v,u); } for (i=1; i<=n; i++) { dis[i][0]=1e9,dis[i][1]=1e9; } dis[1][0]=0; bfs(); int x,l; while (q--) { x=read(),l=read(); if (head[1]==0) printf("No\n"); elseif (l<dis[x][l&1]) printf("No\n"); elseprintf("Yes\n"); } return0; }