本菜的某一周周赛解题报告(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万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章