本菜的某一週周賽解題報告(2016.4.17)

上週周賽題目,網上都能直接找到
其實還是很水的,只要搜索學的還行的幾乎都能AK

Problem A HDU 1036 Average is not Fast Enough!
Problem B CodeForces 652B z-sort
Problem C HDU 1312 Red and Black
Problem D HDU 1429 勝利大逃亡(續)
Problem E HDU 1026 Ignatius and the Princess I

首先是A題,題意表示一下看不懂,但是ACM這類英文題一般都先看樣例會更快的理解題意。
A - Average is not Fast Enough!

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
int main()
{
    int n;
    double d;
    int a;
    scanf("%d%lf",&n,&d);
    while(~scanf("%d",&a)){
        int h,m,s;
        int sum = 0;
        char ss[20]; //因爲如果是--:--:--的話,就不能直接用%d讀
        bool flag = true; // 用來標記記錄裏是否有--:--:--
        getchar();
        for(int i=0;i<n;i++){
            scanf("%s",ss);
            if(ss[0]=='-') flag = false;
            sscanf(ss,"%d:%d:%d",&h,&m,&s);
            sum += h*3600 + m*60 + s;
        }
        if(flag){
            sum = int(sum/d + 0.5); // 整除的處理
            printf("%3d: %d:%2.2d min/km\n",a,sum/60,sum%60);
        }else {
            printf("%3d: -\n",a);
        }
    }
    return 0;
}

代碼寫的不好請不要見怪

然後是B題,B題如果數據小可以暴力搜索,但顯然一般先想想有沒有更好的方法再去寫會更好一點。然後數據貌似很水,被我水過了。

B - z-sort

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
using namespace std;
int a[1010];
int ans[1010];
int main()
{
    int n;
    while(~scanf("%d",&n)){
        for(int i=0;i<n;i++) scanf("%d",&a[i]);
        sort(a,a+n);//直接排序,前一半肯定都比後一半小,所以把後一半都放偶數位,前一半都放奇數位
        int i=0,j=0,tot=0;
        j = (n-1)/2 + 1;
        for(;tot<n;tot++){
            if((tot+1)&1){
                ans[tot] = a[i++];
            }else {
                ans[tot] = a[j++];
            }
        }
        for(int i=0;i<n;i++) {printf("%d",ans[i]);if(i<n-1) printf(" ");}
        printf("\n");
    }
    return 0;
}

水過了B題,然後發現C題更水,就我都能一遍敲出來······
C - Red and Black

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int wayx[] = {1,-1,0,0};
const int wayy[] = {0,0,1,-1};
int mp[30][30];
int uesd[30][30];
int w,h;
int ans;
void dfs(int x,int y)
{
    if(x<=0||x>h||y<=0||y>w||uesd[x][y]==1||mp[x][y]==0) return; //檢查邊界以及走沒走過
    else {
        ans++;
        uesd[x][y]=1;
    }
    for(int i=0;i<4;i++){ //四個方向
        int r,c;
        r = x + wayx[i];
        c = y + wayy[i];
        dfs(r,c);
    }
    return ;
}
int main()
{
    while(scanf("%d%d",&w,&h),w||h){
        memset(uesd,0,sizeof(uesd));
        memset(mp,0,sizeof(mp));
        ans = 0;
        getchar();
        int x,y;
        for(int i=1;i<=h;i++){
            for(int j=1;j<=w;j++){
                char c;
                scanf("%c",&c);
                mp[i][j] = (c=='.'||c=='@') ? 1 : 0;
                if(c=='@'){x = i,y = j;}
            }
            getchar();//讀的時候要小心這些細節
        }
        dfs(x,y);
        printf("%d\n",ans);
    }
    return 0;
}

然後D題開始不水了,這題要一點技巧。
D - 勝利大逃亡(續)

#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <queue>
#include <iostream>
using namespace std;
const int dir[4][2] = {1,0,-1,0,0,1,0,-1};
int n,m,t;
int sx,sy,ex,ey;
char mp[21][21];
int mark[21][21][1024];//用二進制思想:通過擁有鑰匙數來控制不走迴路
struct node
{
    int x,y;
    int key;
    int flag[10]; // 表示擁有的鑰匙
    int step;
};
int a[11]={1,2,4,8,16,32,64,128,256,512}; //二進制打表

bool check(int x,int y,int z,int step) //檢查
{
    if(x>=0&&x<n&&y>=0&&y<m){
        if(mp[x][y]!='*'&&mark[x][y][z]==0&&step<t){
            return true;
        }
    }
    return false;
}


void bfs()
{
    node v,p;
    queue<node> q;
    memset(mark,0,sizeof(mark));
    p.x = sx , p.y = sy;
    p.step = 0;
    p.key = 0;
    for(int i=0;i<10;i++) p.flag[i] = 0;
    q.push(p);
    mark[sx][sy][0] = 1;
    while(!q.empty()){
        p = q.front();
        q.pop();
        for(int i=0;i<4;i++){
            v = p;
            v.x = p.x + dir[i][0];
            v.y = p.y + dir[i][1];
            v.step = p.step + 1;
            if(check(v.x,v.y,v.key,v.step)){
                if(v.x==ex&&v.y==ey){
                    printf("%d\n",v.step);
                    return ;
                }
                else if(mp[v.x][v.y]>='a'&&mp[v.x][v.y]<='j'){
                    if(v.flag[mp[v.x][v.y]-'a']==0){ //注意這裏如果有這把鑰匙,就不要更改鑰匙狀態
                        v.flag[mp[v.x][v.y]-'a'] = 1;
                        v.key += a[mp[v.x][v.y]-'a'];
                    }
                    mark[v.x][v.y][v.key] = 1;
                    q.push(v);
                }
                else if(mp[v.x][v.y]>='A'&&mp[v.x][v.y]<='J'){
                    if(v.flag[mp[v.x][v.y]-'A']==1){
                        mark[v.x][v.y][v.key] = 1;
                        q.push(v);
                    }
                }else {
                   mark[v.x][v.y][v.key] = 1;
                   q.push(v);
                }
            }
        }
    }
    printf("-1\n");

}


int main()
{
    while(~scanf("%d%d%d",&n,&m,&t)){
        getchar();
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                scanf("%c",&mp[i][j]);
                if(mp[i][j]=='@'){
                    sx = i;
                    sy = j;
                }
                if(mp[i][j]=='^'){
                    ex = i;
                    ey = j;
                }
            }
            getchar();
        }
        mp[sx][sy] = '.';
        bfs();
    }
    return 0;
}

對於D題,我只能表示我碼力不夠,T-T,敲了半天
最後E題,額,其實比D題稍微水點,不過貌似要注意以一下內存問題
同時那個輸出問題也要注意一下,不然這種搜索題目一旦出錯,找錯會很難,別問我怎麼知道T-T
E - Ignatius and the Princess I

#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <queue>
#include <iostream>
using namespace std;
struct node
{
    int x,y;
    int step;
    friend bool operator < (node n1,node n2)
    {
        return n2.step<n1.step;
    }
};
int mp[105][105];
int flag[105][105];
int cnt[105][105]; // 記錄要打的怪的HP
int ways[4][2] = {1,0,-1,0,0,1,0,-1};
int n,m,tim;
int check(int x,int y)
{
    if(x<0||y>=m||y<0||x>=n){
        return 1;
    }
    if(mp[x][y]==-1){
        return 1;
    }
    return 0;
}

int bfs()
{
    priority_queue<node> q;
    node a,next;
    a.x = 0;
    a.y = 0;
    a.step = 0;
    mp[0][0] = -1;
    q.push(a);
    while(!q.empty()){
        a = q.top();
        q.pop();
        if(a.x==n-1&&a.y==m-1){
            return a.step;
        }
        for(int i=0;i<4;i++){
            next = a;
            next.x += ways[i][0];
            next.y += ways[i][1];
            if(check(next.x,next.y)){
                continue;
            }
            next.step = a.step + mp[next.x][next.y] + 1; // 記錄時間
            mp[next.x][next.y] = -1; // 標記爲走過
            flag[next.x][next.y] = i+1; //記錄朝向
            q.push(next);
        }
    }
    return 0;
}

void print(int x,int y)
{
    int n_x,n_y;
    if(!flag[x][y])
        return;
    n_x = x - ways[flag[x][y]-1][0];
    n_y = y - ways[flag[x][y]-1][1];
    print(n_x,n_y);
    printf("%ds:(%d,%d)->(%d,%d)\n",tim++,n_x,n_y,x,y);
    while(cnt[x][y]--)
    {
        printf("%ds:FIGHT AT (%d,%d)\n",tim++,x,y);
    }
}



int main()
{
    while(~scanf("%d%d",&n,&m)){
        memset(mp,0,sizeof(mp));
        memset(flag,0,sizeof(flag));
        memset(cnt,0,sizeof(cnt));
        char s[105];
        for(int i=0;i<n;i++){
            scanf("%s",s);
            for(int j=0;s[j];j++){ //對元素進行處理,方便後面處理
                if(s[j]=='.'){
                    mp[i][j] = 0;
                }else if(s[j]=='X'){
                    mp[i][j] = -1;
                }else {
                    mp[i][j] = cnt[i][j] = s[j] - '0'; // 是怪
                }
            }
        }
        int ans=0;
        ans = bfs();
        if(ans){
            printf("It takes %d seconds to reach the target position, let me show you the way.\n",ans);
            tim = 1;
            print(n-1,m-1);
        }else {
            printf("God please help our poor hero.\n");
        }
        printf("FINISH\n");
    }
    return 0;
}

敲完解題,仔細回味發現這種dfs和bfs一定要細心,不然找bug會讓非常難找,另外是邏輯的重要性,以及對題目各種元素屬性,要求的理解,估算空間,估算時間。
特別是做題的時候,一定要分清是用bfs還是dfs
每一題都應該有那麼一個比較清晰的思路,思路不清晰就想清楚再敲,不然很礙事。
最後最重要的,這種題目還是自己碼力不足,還得繼續努力。

以上內容有一定是自己看過別人的才寫出來的,如果有冒犯,請原諒
如果有錯誤請給予更正,謝謝

發佈了40 篇原創文章 · 獲贊 7 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章