グループ19.8.9を試験Jizhongを改善する[シミュレーションゲーム]

チェック柄行くTask.1

タイトル効果:C及びFをみなすことができる\(N \回M \)部屋マトリックスの、行列の各要素があってもよいです。

  1. 障害: "#"

  2. 出発点CまたはF:「C」または「F」

  3. 空き領域:。「」

Cガン伝送を運ぶ、それぞれCであることができます。

  1. 隣接した空き領域に移動した時間の単位

  2. 放射ポータルの縦方向と横方向の一つの壁に時間を費やすことはありません(ポータルは、すでに2がある場合にのみ、2を存在し、最初消える登場扉を起動することができ、場所が二つ存在することはできませんファンポータル)

  3. これは、隣接する壁にトランスファーゲートの前に別のグリッドにモバイルポータルに時間単位を要します。

C Fは最小時間を見つけることができます。

データ範囲:\(1 \のLeq N、M、\のLeq 500 \) マップは、最も外側の障壁であることを確実にします。

https://store.steampowered.com/app/400/Portal/

私たちは、バーストの検索をと思いますか?あなたはそれを生きることができますか?あなたは良い結果85ptsの入手できますか?

正しい操作はこれです:あなたが位置にあるとき、あなたは壁の前に別のポータルに最も近い壁に行くことができるようになります4つの方向に2つのポータルを起動することができます。

アプローチは非常に簡単です:BFSや最短経路アルゴリズムは、その上に検討してください。

コード:

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<vector>
#include<queue>
#include<utility>
using namespace std;

template<class T>void read(T &x){
    x=0; char c=getchar();
    while(c<'0'||'9'<c)c=getchar();
    while('0'<=c&&c<='9'){x=(x<<1)+(x<<3)+(c^48); c=getchar();}
}
typedef pair<int,int> pr;
const int N=505;

int n,m,s,t;
char mp[N][N];
vector<pr>e[N*N];
int num[N][N],L[N][N],R[N][N],U[N][N],D[N][N];
int dis[N*N];
priority_queue<pr>q;
bool vis[N*N];
int dx[5]={0,0,1,-1};
int dy[5]={1,-1,0,0};

void add(int x,int y,int w){e[x].push_back(pr(y,w));}
bool dijkstra(){
    memset(vis,0,sizeof(vis));
    memset(dis,0x7f,sizeof(dis));
    dis[s]=0; q.push(pr(0,s));
    pr now; int x,y,d;
    while(!q.empty()){
        now=q.top(); q.pop();
        x=now.second; if(vis[x])continue; vis[x]=1;
        for(int i=e[x].size()-1;~i;i--){
            y=e[x][i].first; d=e[x][i].second;
            if(dis[y]>dis[x]+d){
                dis[y]=dis[x]+d;
                if(!vis[y])q.push(pr(-dis[y],y));
            }
        }
    }
    return dis[t]!=dis[0];
}
int main(){
    freopen("cell.in","r",stdin);
    freopen("cell.out","w",stdout);
    read(n); read(m); int cnt=0;
    for(int i=1;i<=n;i++){
        scanf("%s",mp[i]+1);
        for(int j=1;j<=m;j++){
            if(mp[i][j]=='#'){L[i][j]=R[i][j]=U[i][j]=D[i][j]=-1; continue;}
            num[i][j]=++cnt;
            if(mp[i][j]=='C') s=num[i][j];
            if(mp[i][j]=='F') t=num[i][j];
            L[i][j]=L[i][j-1]+1; U[i][j]=U[i-1][j]+1;
        }
    }
    for(int i=n;i;i--) for(int j=m;j;j--) if(mp[i][j]!='#'){R[i][j]=R[i][j+1]+1; D[i][j]=D[i+1][j]+1;}
    int nx,ny,d;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++) if(mp[i][j]!='#'){
            for(int k=0;k<4;k++){
                nx=i+dx[k]; ny=j+dy[k];
                if(mp[nx][ny]=='#')continue;
                add(num[i][j],num[nx][ny],1);
            }
            d=min(min(L[i][j],R[i][j]),min(U[i][j],D[i][j]))+1;
            add(num[i][j],num[i][j-L[i][j]],d);
            add(num[i][j],num[i][j+R[i][j]],d);
            add(num[i][j],num[i-U[i][j]][j],d);
            add(num[i][j],num[i+D[i][j]][j],d);
        }
    }
    if(dijkstra()) printf("%d\n",dis[t]);
    else puts("wtf");
    return 0;
}

Task.2ねじれツリー

影響を受ける:あり\は(キー\)キーとして\(ヴァル\)は重量である\(N \)バイナリ検索ツリーは、ノードの定義ポイント\(合計\)そのサブツリーの値を中\(ヴァル\)と。あなたを伝える(N \)\ノード\(キー\)値と\は(ヴァル\)の値は、ツリーの2つのエンドポイントをいずれかの側を満たすために求めている\(キー\)値は最大公約数がされていないです\(1 \)ときにすべてのノードのツリー\(合計\)とどのくらいの最大値です。

范围数据:\(1 \当量N \当量300,1 \当量 key_i当量\ 10 ^ 18,1 \当量val_i \当量10 ^ 6 \)

順序付き二分探索木トラバーサルは、すべてのソート・キーの結果です。ソートしようとした後、\(N- \)の要素が組み合わされて、使用されてもよいアイデア同様の間隔DPが定義されている状態の\(F_ {iは、J、 K} \) の間隔を表す\([I、J]は\ ) に結合され木の部分木のルートである\(K \) 最大回答転送部DPの複雑さに類似している\(O(N ^ 4)\)

間隔:このアイデアは、最適化されている(\ [I、J] \を ) する(K \)を\ルート状況のために、最終的になされなければならない\([I、K-1 ] \) と\([K + 1、J ] \)を取得。そこで、定義された、DP約上述した第3の次元を改善しようとした(F_ {iは、jを、\ 0/1} \) の間隔を表す\([I、J]を\ ) する\(I-1 \)または(\ J + 1 \)は回答のルートである、間隔DPはまだ列挙ルートに類似である転写\(K \)の複雑\(O(N ^ 3)\)

コード:

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<utility>
using namespace std;
template<class T>void read(T &x){
    x=0; char c=getchar();
    while(c<'0'||'9'<c)c=getchar();
    while('0'<=c&&c<='9'){x=(x<<1)+(x<<3)+(c^48); c=getchar();}
}
typedef long long ll;
typedef pair<ll,ll> pr;
const int N=305;
#define key first
#define val second
int n;
pr a[N];
ll sum[N],f[N][N][2],ans;
bool e[N][N];
void cmax(ll &x,ll y){if(x<y)x=y;}
ll gcd(ll x,ll y){return y==0?x:gcd(y,x%y);}
int main(){
    freopen("tree.in","r",stdin);
    freopen("tree.out","w",stdout);
    read(n);
    for(int i=1;i<=n;i++){read(a[i].key); read(a[i].val);}
    sort(a+1,a+n+1);
    if(a[1].key==1){puts("-1"); return 0;}
    memset(f,-0x3f,sizeof(f));
    for(int i=1;i<=n;i++){
        sum[i]=sum[i-1]+a[i].val;
        for(int j=i+1;j<=n;j++)
            e[i][j]=(gcd(a[i].key,a[j].key)!=1);
        if(e[i-1][i]) f[i][i][0]=a[i].val;
        if(e[i][i+1]) f[i][i][1]=a[i].val;
    }
    for(int len=2;len<=n;len++)
        for(int i=1,j=i+len-1;j<=n;i++,j++){
            ll cost=sum[j]-sum[i-1];
            for(int k=i;k<=j;k++){
                ll add=(i<k)*f[i][k-1][1]+(k<j)*f[k+1][j][0]+cost;
                if(e[i-1][k]) cmax(f[i][j][0],add);
                if(e[k][j+1]) cmax(f[i][j][1],add);
                if(len==n) cmax(ans,add);
            }
        }
    printf("%lld\n",ans);
    return 0;
}

Task.3回転磁界

タイトル効果:定義された値が配列配置されている(P_I = iは\)\のような固定小数点の数。今インターバルおよび選択する\([L、R] \ ) 、反転必要後方固定点を反転します。

データ範囲:\(1 \のLeq N \ ^ 5のLeq 10 \。)。

このような性質を有する:位置\を(私は\)の数字\(X \)\(\ FRAC {(I + X)} {2} \) 生成折り畳ま\(1 \) 貢献および場所の数には貢献して対称ポイントが固定されている必要があります。最後のフリップ応答セクションは、次のようになり、再び考えてみましょう:間隔エンドポイントは、対称(レンジの中間点)の少なくとも1つのポイントを持っているフリップに貢献しているか、または2つのエンドポイントが選択した場合、これは答えが良好になることはありませんについて。

小さな半径部分が列挙達し、やる一緒に対称の同じポイントでポイントし、接頭差の使用は答え以外の区間の反転の複雑さ:上記の分析によると、私たちは貪欲なアプローチを考えた\(O(N ^ 2)\) 十分ではない、我々は、フリップのポイント、同じ計算方法と上記の解答をスキップするいかなる貢献を半径を列挙するときにこれらのケースを取り除くために、余分な例をたくさん見られない、近くからの遠端にそれぞれ列挙範囲。そのような各位置のみ複雑一度考えられること\(O(N)\)

コード:

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<vector>
using namespace std;

template<class T>void read(T &x){
    x=0; char c=getchar();
    while(c<'0'||'9'<c)c=getchar();
    while('0'<=c&&c<='9'){x=(x<<1)+(x<<3)+(c^48); c=getchar();}
}
typedef pair<int,int> pr;
void cmax(int &x,int y){if(x<y)x=y;}
void cmin(int &x,int y){if(x>y)x=y;}
const int N=100050;
int n,a[N],pre[N],ans;
vector<int>q[N<<1];
int main(){
    freopen("rotate.in","r",stdin);
    freopen("rotate.out","w",stdout);
    read(n);
    for(int i=1;i<=n;i++){
        read(a[i]); pre[i]=pre[i-1]+(a[i]==i);
        if(a[i]>i) q[a[i]+i].push_back(a[i]);
        else q[a[i]+i].push_back(i);
    }
    int L,R;
    for(int i=(n<<1);i>1;i--){
        sort(q[i].begin(),q[i].end());
        for(int j=0;j<q[i].size();j++){
            R=q[i][j]; L=i-R;
            cmax(ans,pre[L-1]+pre[n]-pre[R]+j+1);
        }
    }
    printf("%d\n",ans);
    return 0;
}

おすすめ

転載: www.cnblogs.com/opethrax/p/11333979.html