The 18th Zhejiang University Programming Contest 總結
阿新 • • 發佈:2019-02-11
刷了一下也沒有時間補題,看了別人的題解,就總結一下:
A:水題
C:指標,連結串列。
F:
題意:
有個容量為c的揹包,兩類物品,其權值分別為k1、k2,第一種物品有n個,第二種有m個,每個物體都有自己的體積。當放進一個物體進入揹包時,其獲得的價值的對應的權值k乘上放入當前物體後剩餘的容量。現在問,能夠獲得的最大價值是多少?
分析:顯然對於同一類物品肯定是從小到大放最好,如果V要放,那比V小的肯定要放,所以物品從小到大排序,d[i][j]表示第一類放進前i個,第二類放進前j個。
總結:多分析題目就能找到dp的狀態
#include<iostream> #include<stdio.h> #include<string.h> #include<algorithm> #include<vector> #include<queue> using namespace std; typedef long long int ll; const ll inf = 1e18; const int maxn = 2000; int n,m; int k1,k2,cap; int a[maxn+5],b[maxn+5]; ll suma[maxn+5],sumb[maxn+5],d[maxn+5][maxn+5]; int main() { int T; scanf("%d",&T); while(T--) { scanf("%d %d %d",&k1,&k2,&cap); scanf("%d %d",&n,&m); ll ans = 0; for(int i=1; i<=n; i++) scanf("%d",&a[i]); for(int i=1; i<=m; i++) scanf("%d",&b[i]); sort(a+1,a+n+1); sort(b+1,b+m+1); for(int i=1;i<=n;i++) suma[i] = suma[i-1]+a[i]; for(int i=1;i<=m;i++) sumb[i] = sumb[i-1]+b[i]; for(int i=0;i<=n;i++) { for(int j=0;j<=m;j++) { if(suma[i]+sumb[j]>cap) break; d[i][j] = 0; if(i>=1) d[i][j] = max(d[i][j],d[i-1][j]+1ll*k1*(cap-suma[i]-sumb[j])); if(j>=1) d[i][j] = max(d[i][j],d[i][j-1]+1ll*k2*(cap-suma[i]-sumb[j])); ans = max(ans,d[i][j]); } //cout<<endl; } printf("%lld\n",ans); } }
G:
基礎的BFS,就是和最短路差不多,
#include<iostream> #include<stdio.h> #include<string.h> #include<algorithm> #include<vector> #include<queue> using namespace std; typedef long long int ll; const int inf = 1e9; const int maxn = 200000; int n,m,sx,sy,tx,ty; struct Node { int x,y,t; }; int f[5][2] = {{1,0},{-1,0},{0,1},{0,-1}}; int g[maxn*4+5],d[maxn*4+5]; int index(int x,int y) { return (x-1)*m + y; } queue<Node>Q; int main() { int T; scanf("%d",&T); while(T--) { scanf("%d %d",&n,&m); for(int i=1; i<=n; i++) { for(int j=1; j<=m; j++) { int inx = index(i,j); scanf("%d",&g[inx]); d[inx] = inf; //d[inx] = inf; } } while(!Q.empty()) Q.pop(); scanf("%d %d %d %d",&sx,&sy,&tx,&ty); Q.push((Node) { sx,sy,0 }); int ans = -1; while(!Q.empty()) { Node no = Q.front(); Q.pop(); int x = no.x, y = no.y, t = no.t, id = index(x,y); int ch = g[id]; if(t%2) ch^=1; d[id] = t; if(x==tx&&y==ty) { ans = t; break; } int l=0,r=2; if(ch) l=2,r=4; for(int i=l; i<r; i++) { int nx = f[i][0] + x, ny = f[i][1] + y; if(nx<1||nx>n||ny<1||ny>m) continue; int tim = t+1, id_ = index(nx,ny); if(d[id_]<=tim) continue; d[id_] = tim;//如果不在這裡更新會超時, Q.push((Node) { nx,ny,tim }); } } printf("%d\n",ans); } return 0; }
H:
題意:給定一個運算式,問是否為真值,如果不是通過加符號來使得變成真值。
分析的不夠,如果是假 可以通過加 |T變為真,所以ans<=2。
原式為真時ans=0,如果可以通過加一個字元就是加!,所以把原式變成&|,判斷即可。
J:水題。