2017-11-8離線賽總結

題目

3817,3818,3819

失分小結

估分

100+100+50=250

實際分數

10+100+0=110

這次炸的十分嚴重.
第一題題目看錯……第三題記憶化搜索炸了

題解

T1

P100

我寫的太垃圾了,僅供參考.

CODE
#include<cstdio>
#include<memory.h>
#include<queue>
#define N 1005
using namespace std;
bool mp[N][N],mark[N][N];
int ans[N][N];
char chr[N];
int n,k;
struct node{int x,y;};
queue<node>Q[2];
int rx[]= { 1, 1, 1,-1,-1,-1, 0, 0};
int ry[]= { 1,-1, 0, 1,-1, 0, 1,-1};

int main() {
    scanf("%d%d",&n,&k);
    for(int i=1; i<=n; i++) {
        scanf("%s",chr);
        for(int j=1; j<=n; j++)
            mp[i][j]=(chr[j-1]=='1');
    }
    memset(ans,63,sizeof ans);
    for(int i=1; i<=n; i++) {
        ans[1][i]=ans[n][i]=ans[i][1]=ans[i][n]=0;
        Q[1].push((node) {1,i});
        Q[1].push((node) {n,i});
        Q[1].push((node) {i,1});
        Q[1].push((node) {i,n});
    }
    int f=1;
    for(; !Q[f].empty(); f^=1)while(!Q[f].empty()) {
        int x=Q[f].front().x,y=Q[f].front().y;
        int z=ans[x][y];
        Q[f].pop();
        if(mark[x][y])continue;
        mark[x][y]=1;
        for(int i=0; i<8; i++) {
            int px=x+rx[i],py=y+ry[i];
            if(px<1||px>n||py<1||py>n)continue;
            if(mp[px][py]||!mp[x][y]) {
                if(ans[px][py]>z) {
                    ans[px][py]=z;
                    Q[f].push((node) {px,py});
                }
            } else {
                if(ans[px][py]>z+1) {
                    ans[px][py]=z+1;
                    Q[!f].push((node) {px,py});
                }
            }
        }
    }
    int a,b;
    k--;
//  for(int i=1; i<=n; i++) {
//      for(int j=1; j<=n; j++)
//          printf("%d ",ans[i][j]);
//      puts("");
//  }
    scanf("%d%d",&a,&b);
    printf("%d",ans[a][b]);
    while(k--) {
        scanf("%d%d",&a,&b);
        printf(" %d",ans[a][b]);
    }
    puts("");
    return 0;
}

T2

這是做的最好的一題…

P100

對於每一種資源,只有第一次出現時(被認爲是稀有資源)和第二次出現時(被認爲是普通資源)有意義,於是可以記錄每種資源第一、二次出現的縱座標,以及上次出現的橫座標。
對於當前資源,
①.若縱座標出現在記錄的第一次之前,則

ans+=(ix1[k])×(y2[k]y1[k])
然後更新x,y.
②.若縱座標出現在記錄第一次之後且在第二次之前,則
ans+=(ix1[k])×(y2[k]j)
然後更新y2.
這樣會漏了第一、二次出現之間靠近底部的部分,最後加上.
想通了還是很水的.
CODE
#include<cstdio>
#define P 19900907
#define N 1105
#define FOR(i,a,b) for(int i=(a),i##_END_=(b);i<=i##_END_;i++)
int X1[N*N],Y1[N*N],Y2[N*N];
long long ans=0;

int main() {
    int n,m;
    scanf("%d %d",&n,&m);
    FOR(i,1,n)FOR(j,1,m) {
        int k;
        scanf("%d",&k);
        if(!X1[k]) {
            X1[k]=i;
            Y2[k]=m+1;
            Y1[k]=j;
        } else if(j<Y1[k]) {
            ans=(ans+1ll*(i-X1[k])*(Y2[k]-Y1[k]))%P;
            X1[k]=i;
            Y2[k]=Y1[k];
            Y1[k]=j;
        } else if(j>=Y1[k]&&j<Y2[k]) {
            ans=(ans+1ll*(i-X1[k])*(Y2[k]-j))%P;
            Y2[k]=j;
        }
    }
    FOR(k,1,n*m)if(X1[k])
        ans=(ans+1ll*(n+1-X1[k])*(Y2[k]-Y1[k]))%P;
    printf("%lld\n",ans);
    return 0;
}

T3

P100

CODE
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#define N 3005
#define M 70005
#define FOR(i,a,b) for(int i=(a),i##_END_=(b);i<=i##_END_;i++)
using namespace std;
inline void rd(int &x) {
    x=0;static char c;
    while(c=getchar(),c<48);
    do x=(x<<1)+(x<<3)+(c&15);
    while(c=getchar(),c>47);
}
int To[M],Nxt[M],Len[M],Head[N],tot;

struct node {
    int x;long long v;
    bool operator< (const node &_)const {
        return v>_.v;
    }
};
int n,m,mark[N],ED[N];
long long dis[N];
vector<int>edge[N];

int main() {
    rd(n),rd(m);
    memset(dis,-1,sizeof dis);
    int st,ed,len;
    FOR(i,1,m) {
        rd(st),rd(ed),rd(len);
        To[++tot]=ed,Nxt[tot]=Head[st],Len[tot]=len,Head[st]=tot;
    }
    int k,x;
    for(int i=1; i<=n; i++) {
        rd(k);
        mark[i]=k;
        for(int j=1; j<=k; j++)rd(x),edge[x].push_back(i);
    }
    priority_queue<node>Q;
    Q.push((node) {1,0});
    dis[1]=0;
    node tmp;
    long long d;
    while(!Q.empty()) {
        tmp=Q.top();
        Q.pop();
        x=tmp.x,d=tmp.v;
        if(dis[x]!=d)continue;
        if(mark[x]) {
            ED[x]=1;
            continue;
        }
        if(x==n){
            printf("%lld\n",d);
            return 0;
        }
        for(int i=0; i<edge[x].size(); i++) {
            int y=edge[x][i];
            mark[y]--;
            if(mark[y]==0&&ED[y]) {
                dis[y]=d;
                Q.push((node) {y,d});
            }
        }
        for(int i=Head[x]; i; i=Nxt[i]) {
            int y=To[i];
            long long t=d+Len[i];
            if(dis[y]==-1||dis[y]>t) {
                dis[y]=t;
                Q.push((node) {y,t});
            }
        }
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章