1. 程式人生 > 資料庫 >Redis持久化與過期機制

Redis持久化與過期機制

A.蜥蜴

將每個石柱拆點,最多可起跳石柱的高度次,入點向出點連其高度的邊。

兩個石柱平面距離不超過d時可互相到達,由一個石柱的出點向另一個石柱的入點連$Inf$邊。

建立源點和匯點。

  當前石柱有蜥蜴時,源點$s$向該石柱入點連容量為$1$的邊。

  當前石柱的橫或縱座標距離邊界最短距離$<d$時,該石柱出點向匯點$t$連$Inf$邊。

跑最大流就是可逃出去最多的蜥蜴數,用總蜥蜴數減去即可。

#include <bits/stdc++.h>
#define Inf 0x3f3f3f3f
using namespace std;
int n,m,d,S,t,ans;
char
s[25]; const int maxn=805; int cnt=-1,head[maxn],vis[maxn]; struct Edge{ int to,next,w; }e[maxn*maxn]; void add(int u,int v,int w) { e[++cnt].to=v; e[cnt].w=w; e[cnt].next=head[u]; head[u]=cnt; e[++cnt].to=u; e[cnt].next=head[v]; head[v]=cnt; } bool Judge(int x,int y,int
xx,int yy) { double temp=sqrt((x-xx)*(x-xx)+(y-yy)*(y-yy)); return temp<=d; } queue<int>q; bool bfs() { q.push(S); memset(vis,0,sizeof(vis)); vis[S]=1; while(!q.empty()) { int u=q.front(); q.pop(); for(int i=head[u];~i;i=e[i].next) {
int v=e[i].to; if(e[i].w&&!vis[v]) { vis[v]=vis[u]+1; q.push(v); } } } return vis[t]; } int dfs(int u,int flow) { if(u==t) return flow; int temp=0,w; for(int i=head[u];~i;i=e[i].next) { int v=e[i].to; if(e[i].w&&vis[v]==vis[u]+1) { w=dfs(v,min(flow-temp,e[i].w)); e[i].w-=w,e[i^1].w+=w,temp+=w; if(temp==flow) return temp; } } if(!temp) vis[u]=0; return temp; } int dinic() { int res=0; while(bfs()) res+=dfs(S,Inf); return res; } int main() { memset(head,-1,sizeof(head)); scanf("%d%d%d",&n,&m,&d); S=0,t=n*m*2+1; for(int i=1;i<=n;++i) { scanf("%s",s+1); for(int j=1;j<=m;++j) { if(s[j]!='0') add((i-1)*m+j,(i-1)*m+j+n*m,s[j]-'0'); } } for(int i=1;i<=n;++i) { scanf("%s",s+1); for(int j=1;j<=m;++j) { if(s[j]=='L') add(S,(i-1)*m+j,1),ans++; } } for(int i=1;i<=n;++i) { for(int j=1;j<=m;++j) { if(i-d<1||i+d>n||j-d<1||j+d>m) add((i-1)*m+j+n*m,t,Inf); } } for(int i=1;i<=n;++i) { for(int j=1;j<=m;++j) { for(int u=1;u<=n;++u) { for(int v=1;v<=m;++v) { if(Judge(i,j,u,v)) add((i-1)*m+j+n*m,(u-1)*m+v,Inf); } } } } printf("%d\n",ans-dinic()); return 0; }
View Code

B.星際戰爭

每個鐳射武器向可攻擊的機器人連一條$Inf$邊。

機器人向匯點連自己的裝甲值。

二分答案 每次二分需要的時間$t$,重建匯點向每個鐳射武器連$B[i]\times t$容量的邊,檢驗最後$A[i]$是否滿流。

處理精度問題可用$long double$,或者因為題目要求精度為$10^{-3}$可將其$\times 1000$,最後輸出答案時除回去即可。

鄰接表清空時不僅$cnt$和$head$陣列要初始化,連結串列$e$也要重置

#include<bits/stdc++.h>
#define Inf 0x3f3f3f3f3f3f3f3f
using namespace std;
const int maxn=50+5;
int n,m,a[maxn],b[maxn],s,t;
bool mapp[maxn][maxn];
int cnt=-1,head[maxn<<1],vis[maxn<<1];
typedef long long ll;
ll sum;
struct Edge{
    int to,next;
    ll w;
}e[maxn*maxn<<1];
void add(int u,int v,ll w) {
    e[++cnt].to=v;
    e[cnt].w=w;
    e[cnt].next=head[u];
    head[u]=cnt;
    e[++cnt].to=u;
    e[cnt].next=head[v];
    head[v]=cnt;
}
queue<int>q;
bool bfs() {
    q.push(s);
    memset(vis,0,sizeof(vis));
    vis[s]=1;
    while(!q.empty()) {
        int u=q.front();
        q.pop();
        for(int i=head[u];~i;i=e[i].next) {
            int v=e[i].to;
            if(e[i].w&&!vis[v]) {
                vis[v]=vis[u]+1;
                q.push(v);
            }
        }
    }
    return vis[t];
}
ll dfs(int u,ll flow) {
    if(u==t) return flow;
    ll temp=0,w;
    for(int i=head[u];~i;i=e[i].next) {
        int v=e[i].to;
        if(e[i].w&&vis[v]==vis[u]+1) {
            w=dfs(v,min(flow-temp,e[i].w));
            e[i].w-=w,e[i^1].w+=w,temp+=w;
            if(flow==temp) return flow;
        }
    }
    if(!temp) vis[u]=0;
    return temp;
}
ll dinic() {
    ll res=0;
    while(bfs()) res+=dfs(s,Inf);
    return res;
}
bool Judge(ll mid) {
    cnt=-1;
    memset(head,-1,sizeof(head));
    memset(e,0,sizeof(e));
    for(int i=1;i<=n;++i) add(i+m,t,a[i]);
    for(int i=1;i<=m;++i)
        for(int j=1;j<=n;++j)
            if(mapp[i][j]) add(i,j+m,Inf);
    for(int i=1;i<=m;++i) add(s,i,mid*b[i]);
    return dinic()>=sum;
}
int main() {
    scanf("%d%d",&n,&m);
    s=0,t=n+m+1;
    for(int i=1;i<=n;++i) scanf("%d",&a[i]),a[i]=a[i]*1000,sum+=a[i];
    for(int i=1;i<=m;++i) scanf("%d",&b[i]);
    for(int i=1;i<=m;++i)
        for(int j=1;j<=n;++j)
            scanf("%d",&mapp[i][j]);
    ll l=0,r=5e9,mid;
    while(l<=r) {
        mid=l+r>>1LL;
        if(Judge(mid)) r=mid-1;
        else l=mid+1;
    }
    printf("%lf\n",(double)l/1000);
    return 0;
}
View Code

D.士兵佔領

源點連行座標,匯點連縱座標。

反向思考,邊容量設定為其最多可不放置的士兵數,假設最初所有能放置士兵的位置先都放置士兵。

行列無障礙,建立一條容量為$1$的邊。

跑出的最大流就是在符合題意的前提下,最多能不放置的士兵數。

#include <bits/stdc++.h>
#define Inf 0x3f3f3f3f
using namespace std;
const int maxn=100+5;
int m,n,k,s,t,hang[maxn],lie[maxn],x,y;
bool mapp[maxn][maxn];
int cnt=-1,head[maxn<<1],vis[maxn<<1];
struct Edge{
    int to,next,w;
}e[maxn*maxn<<1];
void add(int u,int v,int w) {
    e[++cnt].to=v;
    e[cnt].w=w;
    e[cnt].next=head[u];
    head[u]=cnt;
    e[++cnt].to=u;
    e[cnt].next=head[v];
    head[v]=cnt;
}
queue<int>q;
bool bfs() {
    memset(vis,0,sizeof(vis));
    q.push(s);
    vis[s]=1;
    while(!q.empty()) {
        int u=q.front();
        q.pop();
        for(int i=head[u];~i;i=e[i].next) {
            int v=e[i].to;
            if(e[i].w&&!vis[v]) {
                vis[v]=vis[u]+1;
                q.push(v);
            }
        }
    }
    return vis[t];
}
int dfs(int u,int flow) {
    if(u==t) return flow;
    int temp=0,w;
    for(int i=head[u];~i;i=e[i].next) {
        int v=e[i].to;
        if(e[i].w&&vis[v]==vis[u]+1) {
            w=dfs(v,min(flow-temp,e[i].w));
            e[i].w-=w,e[i^1].w+=w,temp+=w;
            if(temp==flow) return temp;
        }
    }
    if(!temp) vis[u]=0;
    return temp;
}
int dinic() {
    int res=0;
    while(bfs()) res+=dfs(s,Inf);
    return res;
}
int main() {
    s=0,t=n+m+1;
    memset(head,-1,sizeof(head));
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1;i<=n;++i) scanf("%d",&hang[i]),hang[i]=m-hang[i];
    for(int i=1;i<=m;++i) scanf("%d",&lie[i]),lie[i]=n-lie[i];
    int flag=0;
    for(int i=1;i<=k;++i) {
        scanf("%d%d",&x,&y);
        mapp[x][y]=1;
        hang[x]--,lie[y]--;
        if(hang[x]<0||lie[x]<0) flag=1;
    }
    if(flag) printf("JIONG!\n");
    else {
        for(int i=1;i<=n;++i) add(s,i,hang[i]);
        for(int i=1;i<=m;++i) add(i+n,t,lie[i]);
        for(int i=1;i<=n;++i) {
            for(int j=1;j<=m;++j) {
                if(!mapp[i][j]) add(i,j+n,1);
            }
        }
    }
    printf("%d\n",n*m-k-dinic());
    return 0;
}
View Code

H.最大獲利

最大權閉合子圖簡單模型。

每個使用者群設定一個節點,源點$s$向其連可獲得收益為$w[i]$的邊,節點向兩個所需的中轉站連$Inf$邊。

每個中轉站向匯點$t$連建立它所需的費用$p[i]$的邊。

初始設定服務所有使用者群,$sum=$獲利$w[i]$的總和,在上圖中跑最小割。

割邊不會為$Inf$邊,那麼就只會為$w[i]$或$p[i]$的邊:

  割$w[i]$時代表失去該使用者群;

  反之保留該使用者群,花費對應的$p[i]$建立中轉站。

答案為$sum-$最小割。

#include <bits/stdc++.h>
#define Inf 0x3f3f3f3f
using namespace std;
const int maxn=6e4+5;
int n,m,x,y,z,s,t,ans;
int cnt=-1,head[maxn],vis[maxn];
struct Edge{
    int to,next,w;
}e[maxn*6];
void add(int u,int v,int w) {
    e[++cnt].to=v;
    e[cnt].w=w;
    e[cnt].next=head[u];
    head[u]=cnt;
    e[++cnt].to=u;
    e[cnt].next=head[v];
    head[v]=cnt;
}
queue<int>q;
bool bfs() {
    memset(vis,0,sizeof(vis));
    q.push(s);
    vis[s]=1;
    while(!q.empty()) {
        int u=q.front();
        q.pop();
        for(int i=head[u];~i;i=e[i].next) {
            int v=e[i].to;
            if(e[i].w&&!vis[v]) {
                vis[v]=vis[u]+1;
                q.push(v);
            }
        }
    }
    return vis[t];
}
int dfs(int u,int flow) {
    if(u==t) return flow;
    int temp=0,w;
    for(int i=head[u];~i;i=e[i].next) {
        int v=e[i].to;
        if(e[i].w&&vis[v]==vis[u]+1) {
            w=dfs(v,min(flow-temp,e[i].w));
            e[i].w-=w,e[i^1].w+=w,temp+=w;
            if(flow==temp) return temp;
        }
    }
    if(!temp) vis[u]=0;
    return temp;
}
int dinic() {
    int res=0;
    while(bfs()) res+=dfs(s,Inf);
    return res;
}
int main() {
    memset(head,-1,sizeof(head));
    scanf("%d%d",&n,&m);
    s=0,t=n+m+1;
    for(int i=1;i<=n;++i) scanf("%d",&x),add(i,t,x);
    for(int i=1;i<=m;++i) scanf("%d%d%d",&x,&y,&z),add(i+n,x,Inf),add(i+n,y,Inf),add(s,i+n,z),ans+=z;
    printf("%d\n",ans-dinic());
    return 0;
}
View Code