【19.11.9】雅礼集团联考
题目
*一个不是很好理解的DP
*考虑过数学和DP,感觉应该是数学但推不出,所以DP没怎么想,但这题的DP的状态转移不是很好想
#include<bits/stdc++.h> #define ri register int #define ll long long #define For(i,l,r) for(ri i=l;i<=r;i++) #define Dfor(i,r,l) for(ri i=r;i>=l;i--) using namespace std; const int M=1e5+5; int n,a[M],b[M]; ll f[M][2]; ll p=1000000007; inline ll read(){ ll f=1,sum=0; char ch=getchar(); while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch)){sum=(sum<<1)+(sum<<3)+(ch^48);ch=getchar();} return f*sum; } int main(){ freopen("choose.in","r",stdin); freopen("choose.out","w",stdout); n=read(); For(i,1,n){ a[i]=read(); } For(i,1,n-1){ b[i]=read(); } f[0][0]=1; For(i,1,n){ f[i][1]=(f[i-1][0]*b[i]%p+f[i-1][1]*b[i]%p)%p; f[i][0]=((f[i-1][1]*((a[i]+b[i-1]-1)%p)%p)+(f[i-1][0]*((a[i]+b[i-1])%p)%p))%p; } printf("%lld\n",(f[n][0]+p)%p); return 0; }
*
#include<bits/stdc++.h> using namespace std; #define MAXN 100010 #define int long long int n,ans,cur,sets[MAXN]; inline int read(){ int x=0, f=1; char ch=getchar(); while(ch<'0' || ch>'9'){ if(ch=='-') f=-1; ch=getchar(); } while(ch>='0' && ch<='9'){ x=x*10+ch-48; ch=getchar(); } return x*f; } struct EData{ int a, b, w; }es[10*MAXN]; struct Node{ int id, x, y, z; }a[MAXN]; bool cmp1(Node a, Node b){ return a.x < b.x; } bool cmp2(Node a, Node b){ return a.y < b.y; } bool cmp3(Node a, Node b){ return a.z < b.z; } bool cmp4(EData a, EData b){ return a.w < b.w; } void add_e(int a, int b, int w){ cur++; es[cur].a = a; es[cur].b = b; es[cur].w = w; } int find_root(int x){ if(sets[x] == x) return x; int root = find_root(sets[x]); sets[x] = root; return root; } bool sets_union(int x, int y){ int x_root = find_root(x); int y_root = find_root(y); if(x_root == y_root) return 0; sets[x_root] = y_root; return 1; } signed main(){ freopen("planet.in","r",stdin); freopen("planet.out","w",stdout); n=read(); for(int i=1; i<=n; i++){ a[i].id = i; a[i].x = read(); a[i].y = read(); a[i].z = read(); } sort(a+1,a+n+1,cmp1); for(int i=1; i<n; i++){ add_e(a[i].id, a[i+1].id, abs(a[i].x-a[i+1].x)); } sort(a+1,a+n+1,cmp2); for(int i=1; i<n; i++){ add_e(a[i].id, a[i+1].id, abs(a[i].y-a[i+1].y)); } sort(a+1,a+n+1,cmp3); for(int i=1; i<n; i++){ add_e(a[i].id, a[i+1].id, abs(a[i].z-a[i+1].z)); } sort(es+1,es+cur+1,cmp4); for(int i=1; i<=n; i++){ sets[i] = i; } for(int i=1; i<=cur; i++){ if(sets_union(es[i].a, es[i].b)) ans += es[i].w; } printf("%lld",ans); return 0; }
*预处理每个点与最近的树木的距离
#include<bits/stdc++.h> using namespace std; #define MAXN 2010 const int bas=1000; int hang,lie,cnt,mp[MAXN][MAXN],d[MAXN][MAXN],dist[MAXN][MAXN],vis[MAXN][MAXN],sx,sy,tx,ty; const int INF=10000000; int dirx[5]={0,0,-1,1}, diry[5]={1,-1,0,0}; char s[MAXN]; inline int read(){ int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9'){ if(ch=='-') f=-1; ch=getchar(); } while(ch>='0'&&ch<='9'){ x=x*10+ch-48; ch=getchar(); } return x*f; } struct Tree{ int x, y; }tr[MAXN*MAXN]; struct FData{ int x,y,g,h; bool operator < (const FData &t) const{ return g+h>t.g+t.h; } }fs[MAXN][MAXN]; priority_queue <FData> q; int check(int x,int y,int r){ int minx=min(2000,x+r); int miny=min(2000,y+r); int maxx=max(1,x-r); int maxy=max(1,y-r); return d[maxx][maxy]-d[maxx][miny-1]-d[minx-1][maxy]+d[minx-1][miny-1]; } int Deal(int x, int y){ int l=0,r=2000,rt=0; while(l<=r){ int mid=l+r>>1; if(check(x,y,mid)){ rt=mid; r=mid-1; }else{ l=mid+1; } } return rt; } int H(int x, int y){ return abs(x-tx)+abs(y-ty); } int D_min_dist(int lim){ memset(vis,0,sizeof(vis)); for(int i=1;i<=hang;i++){ for(int j=1;j<=lie;j++){ fs[i][j].x=i; fs[i][j].y=j; fs[i][j].g=INF; fs[i][j].h=0; } } fs[sx][sy].g=0; fs[sx][sy].h=H(sx,sy); q.push(fs[sx][sy]); while(!q.empty()){ int x=q.top().x; int y=q.top().y; q.pop(); if(vis[x][y]) continue; vis[x][y]=1; for(int i=0;i<4;i++){ int cx=x+dirx[i]; int cy=y+diry[i]; if(cx<1||cx>hang||cy<1||cy>lie) continue; if(dist[cx][cy]<lim) continue; if(vis[cx][cy]) continue; int dis=fs[x][y].g+1; if(fs[cx][cy].g>dis){ fs[cx][cy].g=dis; fs[cx][cy].h=H(cx,cy); q.push(fs[cx][cy]); } } } if(fs[tx][ty].g==INF) return 0; else return 1; } int main(){ freopen("path.in","r",stdin); freopen("path.out","w",stdout); hang=read();lie=read(); for(int i=1;i<=hang;i++){ scanf("%s",s+1); for(int j=1;j<=lie;j++){ if(s[j]=='V'){ sx=i,sy=j; mp[i][j]=2; } else if(s[j]=='J'){ tx=i,ty=j; mp[i][j]=3; } else if(s[j]=='+'){ cnt++; tr[cnt].x=i+j+bas; tr[cnt].y=i-j+bas; d[i+j+bas][i-j+bas]=1; mp[i][j]=-1; } } } for(int i=1;i<=2000;i++){ for(int j=1;j<=2000;j++){ d[i][j]+=d[i][j-1]+d[i-1][j]-d[i-1][j-1]; } } for(int i=1;i<=hang;i++){ for(int j=1;j<=lie;j++){ dist[i][j]=Deal(i+j+bas,i-j+bas)-1; if(mp[i][j]==-1) dist[i][j]++; } } int l=0,r=dist[sx][sy],rt=0; while(l<=r){ int mid=l+r>>1; if(D_min_dist(mid)){ rt=mid; l=mid+1; }else{ r=mid-1; } } printf("%d",rt); return 0; }