考场得分: $0+0+33pts+10pts=43pts$
现在得分: $9pts+0+100pts+100pts=209pts$
T1 Express
T2 Tree
T3 frenzy
背包裸题,但是还是寄了。
令 $dp[i]$ 表示得分为 $i$ 需要的最短时间,转移方程:
$dp[i]=\min\{dp[i],dp[i-p[j]]+t[j]\},i\in[1,k],j\in[1,n],i-p[j]\ge a[j]$
存在有 $p[i],a[i]\ge k$ 的情况,所以初始化请尽可能大。
时间复杂度 $\mathcal O(nk)$
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
| #include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<cstdlib> #include<algorithm> #include<ctime> #include<iomanip> #include<queue> #include<stack> #include<map> #include<vector> #define gh() getchar() #define re register #define db double typedef long long ll; using namespace std; const int MAXN=10001; const long long INF=1e18; template<class T> inline void read(T &x) { x=0; char ch=gh(),t=0; while(ch<'0'||ch>'9') t|=ch=='-',ch=gh(); while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^48),ch=gh(); if(t) x=-x; } template<class T,class ...T1> inline void read(T &x,T1 &...x1) { read(x),read(x1...); } template<class T> inline bool checkMax(T &x,T &y) { return x<y?x=y,1:0; } template<class T> inline bool checkMin(T &x,T &y) { return x>y?x=y,1:0; } int Test,n,k; struct Fish { ll a,p,t; }val[MAXN]; ll dp[MAXN*10],mxP; inline void init() { mxP=0; read(n,k); for(int i=1;i<MAXN;++i) dp[i]=INF; for(int i=1;i<=n;++i) read(val[i].a,val[i].p,val[i].t); for(int i=1;i<=n;++i) checkMax(mxP,val[i].p); } inline ll dpCnt(int n,int x) { dp[0]=0; for(int i=1;i<x+mxP;++i) for(int j=1;j<=n;++j) if(val[j].a<=i-val[j].p) dp[i]=min(dp[i],dp[i-val[j].p]+val[j].t); ll ans=INF; for(int i=x;i<x+mxP;++i) checkMin(ans,dp[i]); return ans; } int main() { read(Test); while(Test--) { init(); printf("%lld\n",dpCnt(n,k)); } return 0; }
|
T4 castle
状压裸题,但是还是寄了。
其实应该要想到的,毕竟一个 $n\le 17$ 就摆在那儿,可能是因为在做前两道题,所以就糊了一个 $Dijkstra$ 过去,还骗了 $10pts$ 就离谱。
以 $dp[s][i]$ 表示当前状态为 $s$ ,当前位置为 $i$ 的最长路径。(这里的 $i$ 应该是 $i\in [0,n-1]$ 的,方便于状态压缩的表示,表示类似于哈密顿路径那道题)
为什么是最长路径?在最后的答案,我们用 $cnt$ 表示经过路径的怪物和,用 $dp[s_0][T]$ 表示路径长度,则有 $ans=\min\{\frac{cnt}{dp[s_0][T]}\}$ ,那么,在 $cnt$ 相等的情况下,则 $dp[s_0][T]$ 越大, $ans$ 越小。(这就是为什么我第二个样例一直调不出来的原因)
转移方程:
$dp[s][ed]=\min\{dp[s][st]+path[st][ed]\},c(st,ed)\in E,st,ed\in s$
即可,我因为一直调不出来,就把重边记录了最大值和最小值,然后建反边跑了两次,实际上是不需要的。
时间复杂度 $\mathcal O(n^22^n)$ 。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
| #include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<cstdlib> #include<algorithm> #include<ctime> #include<iomanip> #include<queue> #include<stack> #include<map> #include<vector> #define gh() getchar() #define re register #define db double typedef long long ll; using namespace std; const int MAXN=21; const int MAXM=520; const int MAXS=(1<<18)+1; const int INF=0x3f3f3f3f; template<class T> inline void read(T &x) { x=0; char ch=gh(),t=0; while(ch<'0'||ch>'9') t|=ch=='-',ch=gh(); while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^48),ch=gh(); if(t) x=-x; } template<class T,class ...T1> inline void read(T &x,T1 &...x1) { read(x),read(x1...); } template<class T> inline bool checkMax(T &x,T &y) { return x<y?x=y,1:0; } template<class T> inline bool checkMin(T &x,T &y) { return x>y?x=y,1:0; } int N,M,val[MAXN],path[3][MAXN][MAXN]; int dp[3][MAXS][MAXN]; double ans=INF; inline void dpSP(int op,int St,int Ed) { for(int s=0;s<(1<<N);++s) for(int st=0;st<N;++st) if((s>>st)&1) for(int ed=0;ed<N;++ed) if(((s>>ed)&1)&&path[op][st][ed]!=-1&&dp[op][s-(1<<ed)][st]!=-1) dp[op][s][ed]=max(dp[op][s][ed],dp[op][s-(1<<ed)][st]+path[op][st][ed]); for(int s=0;s<(1<<N);++s) if(((s>>St)&1)&&((s>>Ed)&1)&&dp[op][s][Ed]>0) { int cnt=0; for(int i=0;i<N;++i) if((s>>i)&1) cnt+=val[i]; double res=(cnt*1.0)/(dp[op][s][Ed]*1.0); checkMin(ans,res); } return ; } int main() { read(N,M); for(int i=0;i<N;++i) read(val[i]); for(int op=0;op<=1;++op) for(int i=0;i<N;++i) { for(int j=0;j<N;++j) path[op][i][j]=-1; path[op][i][i]=0; } for(int i=1,u,v,w;i<=M;++i) { read(u,v,w); checkMin(path[0][u-1][v-1],w); checkMax(path[1][v-1][u-1],w); } int S,T; read(S,T); --S;--T; for(int op=0;op<=1;++op) for(int s=0;s<(1<<N);++s) for(int i=0;i<N;++i) dp[op][s][i]=-1; dp[0][(1<<S)][S]=0; dp[1][(1<<T)][T]=0; dpSP(0,S,T); dpSP(1,T,S); printf("%.3lf",ans); return 0; }
|