2019年8月18日の概要

T1の郵便配達メッセンジャー100/100

問題の意味

ノード1で、郵便局に物事を送信するために郵便配達員があります。N-1の彼の合計が先2ある事を、送信するために〜N. 街の忙しい交通のため、すべての道路が一方通行なので、Mの道路の合計は、各道路を通じてある程度の時間がかかります。郵便配達は一つだけをもたらすことができます。このN-1株が何かを求めて、最終的に郵便局に戻ってしばらくは時間の最小量を必要とします。

我々が記載見つけることは容易である(\ sum_ {J = 1} ^ N- \)\ [1]〜[J] SPFA再度でき、それはDISのために、実行spfaを意図されている[1] [1]〜[J] + DIS [J] DISしかし、実行n回spfa重要な残業場合DIS [j]は、[1]、解決されていないが、我々は抗マップ、ノード1の実行spfaを確立し、アイデアを変更することができ、その後、他のポイントへのノードは距離ではないんです解決するためにノード点までの距離。

コード

#include<bits/stdc++.h>
using namespace std;
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<<1)+(x<<3)+(ch^48);
        ch=getchar();
    }
    return x*f;
}
const int N=1010,M=100010;
int head[N][2],ver[M][2],edge[M][2],Next[M][2],d[N][2];
int n,m,tot1,tot2;
long long ans;
bool v[N];
queue<int> q;
void add(int x,int y,int z){
    ver[++tot1][0]=y;edge[tot1][0]=z;Next[tot1][0]=head[x][0],head[x][0]=tot1;
}
void add1(int x,int y,int z){
    ver[++tot2][1]=y;edge[tot2][1]=z;Next[tot2][1]=head[x][1],head[x][1]=tot2;
}
void spfa(){
    memset(d,0x3f,sizeof(d));
    d[1][0]=0,v[1]=1;
    q.push(1);
    while(q.size()){
        int x=q.front();q.pop();
        v[x]=0;
        for(int i=head[x][0];i;i=Next[i][0]){
            int y=ver[i][0],z=edge[i][0];
            if(d[y][0]>d[x][0]+z){
                d[y][0]=d[x][0]+z;
                if(!v[y]) q.push(y),v[y]=1;
            }
        }
    }
    while(!q.empty()) q.pop();
    memset(v,0,sizeof(v));
    d[1][1]=0,v[1]=1;
    q.push(1);
    while(q.size()){
        int x=q.front();q.pop();
        v[x]=0;
        for(int i=head[x][1];i;i=Next[i][1]){
            int y=ver[i][1],z=edge[i][1];
            if(d[y][1]>d[x][1]+z){
                d[y][1]=d[x][1]+z;
                if(!v[y]) q.push(y),v[y]=1;
            }
        }
    }
}
int main(){
    n=read();m=read();
    for(int i=1;i<=m;++i){
        int x,y,z;
        x=read();y=read();z=read();
        add(x,y,z);
        add1(y,x,z);
    }
    spfa();
    for(int i=1;i<=n;++i){
        ans+=d[i][0]+d[i][1];
    }
    printf("%lld",ans);
    return 0;
}

T2は、レンガ70/100をノック

問題の意味

レンガのN層が上から下へレンガ減少都度、油Nレンガの最上層に前記凹部内に配置されます。図に示すように、各ブリックのスコアを有し、このレンガは、対応する値をノック得ることができます。

あなたが最初のレンガ層I jをノックしたい場合はI = 1ならば、その後、あなたはそれをノックアウトすることができます; I> 1なら、あなたは私-1番目の層とj-jは+をノックダウンする必要があります。 1個のレンガ。

あなたは今ではほとんどの数を獲得しているしようとしている、Mレンガまでノックすることができます。

問題Dpは、ラインDPによってラインを考えるようになった発見された、しかし、選択し[i、j]が選ぶだろう[I-1、jは+ 1 ] と[私は、j]は上記のすべてのボックスは、何の後遺症が満たされていないんようですセックスは、どのようにそれを行うには?
我々は、このようなファイルの入力を見つけたら

4 5
2 2 3 4
8 2 7
2 3
49

私たちは、そう何の後遺症n列からDPに、A DPは不可能ではないと考えるために行くことができ、我々は、Fの状態を定義することができます[I] [J] [k]はi番目の列に電流を表しj番目から選択されますK選挙、状態遷移方程式の合計

F [I] [J] [K] = MAX(F [I + 1] [T] [KJ] + S [i]は[J]、F [i]は[J] [K])

T> = J-1 && T <= NI

S [i] [j]は、i番目の前に、j番目の列を表し、

コード

#include<bits/stdc++.h>
using namespace std;
int n,m,ans,f[55][55][3000],a[55][55],s[55][55];
int main(){
    scanf("%d %d",&n,&m);
    memset(f,-0x3f,sizeof(f));
    f[n+1][0][0]=0;
    for(int i=1;i<=n;++i){
        for(int j=1;j<=n-i+1;++j){
            scanf("%d",&a[i][j]);
        }
    }   
    for(int i=1;i<=n;++i){
        for(int j=1;j<=n-i+1;++j){
            s[j][i]=s[j][i-1]+a[i][j];
        }
    }
    for(int i=n;i>=1;--i){
        for(int j=0;j<=n-i+1;++j){
            for(int k=j;k<=m;++k){
                for(int t=max(j-1,0);t<=n-i;++t){
                    f[i][j][k]=max(f[i+1][t][k-j]+s[i][j],f[i][j][k]);
                }
            }
        }
    }
    for(int i=1;i<=n;++i){
        for(int j=1;j<=n-i+1;++j){
            ans=max(ans,f[i][j][m]);
        }
    }
    printf("%d",ans);
    return 0;
}

T3同等の表現30/0

問題の意味

発現した後、nの表現を与えるために、かどうか、同等の決定

アナログ大きな問題、数、および剰余でオーバーフローを防ぎます

#include<bits/stdc++.h>
using namespace std;
const int mod=10007;
char w[55],c[55];
int a[100],t1,t2,x,n;
long long ans[5],c1[55],c2[55],c3[55];
int power(int x,int y){
    int tmp=1;
    while(y){
        if(y&1) tmp=(tmp*x)%mod;
        x=(x*x)%mod;
        y>>=1;
    }
    return tmp%mod;
}
void clu(){
    int m1=c1[t2],n1=c1[t2-1],m2=c2[t2],n2=c2[t2-1],m3=c3[t2],n3=c3[--t2]; 
    switch(w[t1--]){
        case '+':c1[t2]=(n1+m1+mod)%mod; c2[t2]=(n2+m2+mod)%mod; c3[t2]=(n3+m3+mod)%mod; break;
        case '-':c1[t2]=(n1-m1+mod)%mod; c2[t2]=(n2-m2+mod)%mod; c3[t2]=(n3-m3+mod)%mod; break;
        case '*':c1[t2]=(n1*m1+mod)%mod; c2[t2]=(n2*m2+mod)%mod; c3[t2]=(n3*m3+mod)%mod; break;
        case '^':c1[t2]=power(n1,m1); c2[t2]=power(n2,m2); c3[t2]=power(n3,m3); break;
    }
}
void js(){
    x=0;
    for(int i=0;i<strlen(c);i++){
        if(c[i]=='a') {c1[++t2]=3;c2[t2]=7;c3[t2]=13;} 
        else if(isdigit(c[i])) x=x*10+c[i]-'0';
        else{
            if(x!=0){c1[++t2]=x;c2[t2]=x;c3[t2]=x;x=0;}
            if(a[c[i]]==0)continue;
            if(c[i]=='('||t1==0&&c[i]!=')') w[++t1]=c[i]; 
            else{ 
                if(a[c[i]]<a[w[t1]]){
                    if(c[i]!=')') w[++t1]=c[i]; 
                    else{ 
                        while(w[t1]!='('&&t1) clu();   
                        if(w[t1]=='(')t1--;
                    }
                }  
                else{
                    while(a[c[i]]>=a[w[t1]]&&t1) clu(); 
                    if(c[i]!=')') w[++t1]=c[i];
                }
            } 
        }
    }
    if(x!=0){c1[++t2]=x;c2[t2]=x;c3[t2]=x;x=0;}
    while (t1)clu();
}
int main(){
    a['(']=5;a[')']=1;a['^']=2;a['*']=a['/']=3;a['+']=a['-']=4;
    gets(c);
    scanf("%d",&n);
    js();
    gets(c);
    ans[1]=c1[1];ans[2]=c2[1];ans[3]=c3[1];
    for(int i=1;i<=n;++i){
        t1=t2=0;gets(c);js(); 
        if(ans[1]==c1[1]%mod&&ans[2]==c2[1]%mod&&ans[3]==c3[1]%mod) 
        printf("%c",i+64);
    }
    return 0;
} 

T4拡散100/100

問題の意味

間違った考えを誤解するのは簡単何についての講演

時間を最小限にするために、各点に対して最短マンハッタン距離を行って、その後、最大値をとり、それは時間(MAXN + 1)/ 2です。

コード

#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<iostream>
#define ll long long
#define MX 55
using namespace std;
int d[MX][MX];
int x[MX],y[MX];
int ans=0;
int man=1<<30;
int n;
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;++i){
        scanf("%d %d",&x[i],&y[i]);
    }
    for(int i=1;i<=n;++i){
        for(int j=i+1;j<=n;++j){
            d[i][j]=d[j][i]=(abs(x[i]-x[j])+abs(y[i]-y[j]));
        }
    }
    for(int i=1;i<=n;++i){
        man=1<<30;
        for(int j=1;j<=n;++j){
            if(i==j) continue;
            man=min(d[i][j],man);
        }
        ans=max(ans,man);
    }
    printf("%d",(ans+1)/2);
    return 0;
}

これを行うにはわずか20分で、なぜそれが間違っていますか?

それぞれが最小のエッジを服用すると、あなたは、エッジのいくつかは全く選挙を選択する必要がありません欠場することができますので、それはあなたの例を与える、中国聯通のブロックなしにつながる選択しません

上記方法によれば場合のみ赤エッジに選択されるが、黒側ブロックはそれほど間違っていない通信リンクにつながる群から選択される少なくとも一種であるだろう。

正解

より独創的な方法は、半分ができユニコムの互いに素なセットまたはBFSを決定することができるマンハッタン距離の最短最長の距離を見つけるために考慮することができます。

コード

#include<bits/stdc++.h>
using namespace std;
int n,ans,l,r,cnt,fa[60],zx[60],zy[60];
int find(int x){
    if(x==fa[x]) return x;
    else return fa[x]=find(fa[x]);
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;++i){
        scanf("%d %d",&zx[i],&zy[i]);
    }
    l=0,r=1e9;
    while(l<=r){
        int mid=(l+r)>>1;
        for(int i=1;i<=n;++i){
            fa[i]=i;
        }
        for(int i=1;i<=n;++i){
            for(int j=i+1;j<=n;++j){
                int dis=abs(zx[i]-zx[j])+abs(zy[i]-zy[j]);
                if(dis<=mid*2){
                    int fa1=find(i);
                    int fa2=find(j);
                    if(fa1!=fa2) fa[fa1]=fa2;
                }
            }
        }
        cnt=0;
        for(int i=1;i<=n;++i){
            if(fa[i]==i) cnt++;
        }
        if(cnt==1) r=mid-1;
        else l=mid+1;
    }
    printf("%d",l);
    return 0;
}

この問題は、さらに時間に任意の2点間のリンクを計算し、最小スパニングツリー(MST)ができ、最大側のMSTは答えです。MSTの性質があるため、最大の一つは、任意の2点間の最小のエッジ重みを満たします。

概要、今日の試験全体的な大丈夫、長い時間のための等価な式の曲は、getlineのを使用する方法がわかりません。アナログまたはなじみのない、あまりにも少し練習のために、コードでは、この話題について書いて、強力ではありません。

おすすめ

転載: www.cnblogs.com/donkey2603089141/p/11414998.html