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)