2017.10.15 补题: F.J

本文通过实战案例探讨了链表操作与贪心算法的应用技巧。针对具体问题,介绍了如何利用链表进行高效的数据管理和搜索,并通过枚举斜率的方法实现贪心策略,以达到最优解。

F的链表其实很水,只是我老想着边做边输出,这样当然不可能,,可能还是链表用的不太熟练。。
看别人很快的代码:https://vjudge.net/solution/11074286

J题:
参考:https://vjudge.net/solution/11080538
根据贪心的原则,要把时间都用完,所以枚举一下斜率来看时间是多少。

H题:
参考:https://vjudge.net/solution/11078116
分两者情况,反正很好的考验代码能力的题目。

#include <bits/stdc++.h>
using namespace std;
#define N 16
#define INF 100000000
#define LL long long
#define P pair<int,int>
#define fi first
#define se second
int n,m;
int typ[N][N];
char tu[N][N];
int dx[]={0,1,0,-1},dy[]={1,0,-1,0};
int cnt;
P pre[N][N][N][N];
int dis[N][N][N][N];

void dfs(int x,int y){
    typ[x][y]=cnt;
    for(int i=0;i<4;++i){
        int nx=x+dx[i],ny=y+dy[i];
        if(nx<1||nx>n||ny<1||ny>m||typ[nx][ny]||tu[nx][ny]=='.')continue;
        dfs(nx,ny);
    }
}
bool Min(int &x,int y){
    if(x>y)x=y;return 1;
    return 0;
}
void init(int sx,int sy){
    for(int i=1;i<=n;++i)
        for(int j=1;j<=m;++j)
            dis[sx][sy][i][j]=INF;
    dis[sx][sy][sx][sy]=0;
    queue<P>Q;
    Q.push(P(sx,sy));
    while(!Q.empty()){
        P tmp=Q.front();Q.pop();
        int x=tmp.fi,y=tmp.se;
        for(int i=0;i<4;++i){
            int nx=x+dx[i],ny=y+dy[i];
            if(nx<1||nx>n||ny<1||ny>m){
                if(Min(dis[sx][sy][n][m],dis[sx][sy][x][y]+1)){
                    pre[sx][sy][n][m]=P(x,y);
                }continue;
            }
            if(tu[nx][ny]=='X'){
                if(Min(dis[sx][sy][nx][ny],dis[sx][sy][x][y]+1)){
                    pre[sx][sy][nx][ny]=P(x,y);
                }
            }
            if(dis[sx][sy][nx][ny]!=INF)continue;
            dis[sx][sy][nx][ny]=dis[sx][sy][x][y]+1;
            pre[sx][sy][nx][ny]=P(x,y);
            Q.push(P(nx,ny));
        }
    }
}
int ans=INF,ans1=INF;

void find1(P a2,P a1){
    int nowx=a1.fi,nowy=a2.se;
    int ex=a2.fi,ey=a2.se;
    while(nowx!=ex||nowy!=ey){
        if(tu[nowx][nowy]=='.')tu[nowx][nowy]='*';
        int nx=pre[ex][ey][nowx][nowy].fi;
        int ny=pre[ex][ey][nowx][nowy].se;
        nowx=nx;nowy=ny;
    }
    if(tu[nowx][nowy]=='.')tu[ex][ey]='*';
}
P poi[3];
int main(){
    while(~scanf("%d%d",&n,&m)){
        memset(typ,0,sizeof(typ));
        memset(dis,0x3f,sizeof(dis));
        cnt=0;
        for(int i=1;i<=n;++i)
            for(int j=1;j<=m;++j)
                scanf("%c",&tu[i][j]);
        for(int i=1;i<=n;++i)
            for(int j=1;j<=m;++j)
                if(!typ[i][j]&&tu[i][j]=='X')++cnt,dfs(i,j);
        for(int i=1;i<=n;++i)
            for(int j=1;j<=m;++j)
                printf("%d%c",typ[i][j],j==m?'\n':' ');
        for(int i=1;i<=n;++i)
            for(int j=1;j<=m;++j)
                init(i,j);
        int ff=0;
        int ans=INF;
        for(int s1=1;s1<=n;++s1)
            for(int s2=1;s2<=m;++s2){
                if(tu[s1][s2]=='.')continue;
                for(int s3=1;s3<=n;++s3)
                    for(int s4=1;s4<=m;++s4){
                        if(tu[s3][s4]=='.'||typ[s1][s2]==typ[s3][s4])continue;
                        if(Min(ans,dis[s1][s2][n][m]+dis[s3][s4][n][m])){
                            ff=0;poi[1]=P(s1,s2);poi[2]=P(s3,s4);
                        }
                        for(int s5=1;s5<=n;++s5){
                            for(int s6=1;s6<=m;++s6){
                                if(tu[s5][s6]=='X')continue;
                                if(Min(ans,dis[s1][s2][s5][s6]+dis[s3][s4][s5][s6]+dis[s5][s6][n][m])){
                                    ff=1;poi[0]=P(s5,s6),poi[1]=P(s1,s2),poi[2]=P(s3,s4);
                                }
                            }
                        }
                    }
            }
        if(ff){
            find1(poi[0],poi[1]);
            find1(poi[0],poi[2]);
            find1(poi[0],P(n,m));
        }
        else{
            find1(poi[1],P(n,m));
            find1(poi[2],P(n,m));
        }
        for(int i=1;i<=n;++i)
            for(int j=1;j<=m;++j)
                cout<<tu[i][j];
    }
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值