微软2017年预科生计划在线编程笔试-#1491 : Monster Killing

http://hihocoder.com/problemset/problem/1491

题意理解:总共的格子数《=20,并且不同状态只有6个,所以可以f【sta】【r】装压,表示sta解决了,目前无敌是r,然后枚举下一次解决的是谁,每次一口气解决一个。根据题意模拟,注意新开一个格子需要1个round.

急转弯:装压,每次解决一个。注意每次枚举的要是新格子,不然一直刷S可能会有错的。

算法:无。

数据结构:无。

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

const int maxn = 20 + 5;
const int MAXSTA = (1 << 20) + 100;
int dx[5] = {-1, 0, 1, 0};
int dy[5] = {0, 1, 0, -1};

int t_mp[maxn][maxn], no_mp[maxn][maxn], vis[maxn][maxn], in_Hi[maxn], in_Ai[maxn], f[MAXSTA][10];
char mp[maxn][maxn];
int Di, Dj;
int N, M, key, no;
int in_Hp, in_Ap;

int getSta(int x, int y) {
    return (1 << (x * M + y));
}

void changeToMat(int sta) {
    memset(t_mp, 0, sizeof(t_mp));
    for(int x = 0; x < N; x++) {
        for(int y = 0; y < M; y++){
            int t = getSta(x, y);
            if((sta & t) != 0) {
                t_mp[x][y] = 1;
            }
        }
    }
}

int logic(int x, int y){
    if (x < N && x >= 0 && y < M && y >= 0) return 1;
    return 0;
}

int dfs(int x, int y){
    int ans = 1;
    vis[x][y] = 1;
    for(int k = 0; k < 4; k++){
        int tx = x + dx[k], ty = y + dy[k];
        if(logic(tx, ty) && vis[tx][ty] == 0 and t_mp[tx][ty] == 1) {
            ans += dfs(tx, ty);
        }
    }
    return ans;
}

int check() {
    int cnt = 0;
    for(int x = 0; x < N; x++) {
        for(int y = 0; y < M; y++) {
            if(t_mp[x][y] == 1) cnt++;
        }
    }
    memset(vis, 0, sizeof(vis));
    int t = dfs(Di, Dj);
    if(t == cnt) return 1;
    return 0;
}

int hasNei(int x, int y) {
    for(int k = 0; k < 4; k++) {
        int tx = x + dx[k], ty = y + dy[k];
        if(logic(tx, ty) && t_mp[tx][ty] == 1) return 1;
    }
    return 0;
}
int main(){
    scanf("%d%d", &N, &M);
    key = (1 << (N * M));
    no = 0;
    for(int i = 0; i < N; i++) {
        scanf("%s", mp[i]);
        for(int j = 0; j < M; j++){
            if(mp[i][j] == 'S' || mp[i][j] == 'M') {
                no_mp[i][j] = no;
                no += 1;
            }
            if(mp[i][j] == 'D') {
                Di = i;
                Dj = j;
            }
        }
    }
    for(int i = 0; i < no; i++){
        scanf("%d%d", &in_Hi[i], &in_Ai[i]);
    }
    scanf("%d%d", &in_Hp, &in_Ap);
    memset(f, 0, sizeof(f));
    f[getSta(Di, Dj)][5] = in_Hp;
    for(int sta = 0; sta < key; sta++) {
        changeToMat(sta);
        if(check() == 0) {
            continue;
        }
        for(int r = 0; r <= 5; r++) {
            if(f[sta][r] == 0) continue;
            for(int x = 0; x < N; x++) {
                for(int y = 0; y < M; y++) {
                    if(hasNei(x, y) == 0 || ((getSta(x, y)&sta) != 0)) continue;
                    if(mp[x][y] == '.') {
                        int nsta = sta | getSta(x, y);
                        int nr = max(0, r - 1);
                        f[nsta][nr] = max(f[nsta][nr], f[sta][r]);
                    } else{
                        int r_ = max(0, r - 1);
                        int Hi = in_Hi[no_mp[x][y]];
                        int Ai = in_Ai[no_mp[x][y]];
                        int Hp = f[sta][r];
                        int Ap = in_Ap;
                        if(r_ * Ap >= Hi) {
                            int nr = r_ - (Hi + Ap - 1) / Ap;
                            int nsta = (sta | getSta(x, y));
                            if(mp[x][y] == 'S') nr = 5;
                            f[nsta][nr] = max(f[nsta][nr], f[sta][r]);
                        } else {
                            int nr = 0;
                            int nsta = sta | getSta(x, y);
                            int Hi_ = Hi - r_ * Ap;
                            int Hp_ = Hp - (Hi_ + Ap - 1) / Ap * Ai;
                            if(mp[x][y] == 'S') nr = 5;
                            f[nsta][nr] = max(f[nsta][nr], Hp_);
                        }
                    }
                }
            }
        }
    }
    int res = 0;
    for(int i = 0; i <= 5; i++) res = max(res, f[key - 1][i]);
    if(res == 0) printf("DEAD\n");
    else printf("%d\n", res);
    return 0;
}








python太慢了。。预处理联通的sta可能就超时了,还有其他办法,但是就不弄了。

#
#

'test python speed'

__author__ = 'hjkruclion'

import sys

def read_int():
    return list(map(int, sys.stdin.readline().split()))
def read_str():
    return sys.stdin.readline().split()[0]

maxn = 20 + 5
MAXSTA = (1 << 20) + 100
dx = [-1, 0, 1, 0]
dy = [0, 1, 0, -1]

mp = [['.' for j in range(maxn)] for i in range(maxn)]
t_mp = [[0 for j in range(maxn)] for i in range(maxn)]
no_mp = [[0 for j in range(maxn)] for i in range(maxn)]
vis = [[0 for j in range(maxn)] for i in range(maxn)]
in_Hi = [0 for i in range(maxn)]
in_Ai = [0 for i in range(maxn)]
f = [[0 for j in range(7)] for i in range(MAXSTA)]

Di = Dj = 0
N, M = read_int()
key = (1 << (N * M))
no = 0
# print(N, M)
for i in range(N):
    t = read_str()
    for j in range(M):
        mp[i][j] = t[j]
        if mp[i][j] == 'S' or mp[i][j] == 'M':
            no_mp[i][j] = no
            no += 1
        if mp[i][j] == 'D':
            Di = i
            Dj = j
for i in range(no):
    in_Hi[i], in_Ai[i] = read_int()
in_Hp, in_Ap = read_int()

def changeToMat(sta):
    global t_mp
    for x in range(0, N):
        for y in range(0, M):
            t = getSta(x, y)
            if (sta & t) != 0:
                t_mp[x][y] = 1
            else:
                t_mp[x][y] = 0

def logic(x, y):
    if x < N and x >= 0 and y < M and y >= 0:
        return True
    return False

def dfs(x, y):
    ans = 1
    global t_mp, vis
    vis[x][y] = 1
    for k in range(4):
        tx = x + dx[k]
        ty = y + dy[k]
        if logic(tx, ty) and vis[tx][ty] == 0 and t_mp[tx][ty] == 1:
            ans += dfs(tx, ty)
    return ans

def check():
    global t_mp, vis
    cnt = 0
    for x in range(0, N):
        for y in range(0, M):
            vis[x][y] = 0
            if t_mp[x][y] == 1:
                cnt += 1

    t = dfs(Di, Dj)
    if t == cnt:
        return True
    else:
        return False

def getSta(x, y):
    return (1 << (x * M +  y))

def hasNei(x, y):
    global t_mp
    for k in range(4):
        tx = x + dx[k]
        ty = y + dy[k]
        if logic(tx, ty) and t_mp[tx][ty] == 1:
            return True
    return False


f[getSta(Di, Dj)][5] = in_Hp
# print(in_Hp)
for sta in range(key):
    # print(sta)
    changeToMat(sta)
    if not check():
        continue
    for r in range(6):
        if f[sta][r] == 0:
            continue
        for x in range(N):
            for y in range(M):
                if not hasNei(x, y) or ((getSta(x, y)&sta) != 0):
                    continue
                if mp[x][y] == '.':
                    nsta = sta | getSta(x, y)
                    nr = max(0, r - 1)
                    f[nsta][nr] = max(f[nsta][nr], f[sta][r])
                else:
                    r_ = max(0, r - 1)
                    Hi = in_Hi[no_mp[x][y]]
                    Ai = in_Ai[no_mp[x][y]]
                    Hp = f[sta][r]
                    Ap = in_Ap
                    if r_ * Ap >= Hi:
                        nr = r_ - (Hi + Ap - 1) // Ap
                        nsta = sta | getSta(x, y)
                        if mp[x][y] == 'S':
                            nr = 5
                        f[nsta][nr] = max(f[nsta][nr], f[sta][r])
                    else:
                        nr = 0
                        nsta = sta | getSta(x, y)
                        Hi_ = Hi - r_ * Ap
                        # print(Hi_, Hp)
                        Hp_ = Hp - (Hi_ + Ap - 1) // Ap * Ai
                        # print('now:', Hi_, Hp_)
                        if mp[x][y] == 'S':
                            # print(Hp_, x, y)
                            nr = 5
                        f[nsta][nr] = max(f[nsta][nr], Hp_)

res = 0
for i in range(6):
    res = max(res, f[key - 1][i])
if res == 0:
    print('DEAD')
else:
    print(res)



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值