一开始就在做1004,然后做了一开始看成是每一把钥匙只有一把,然后就wa了,下面是wa了的代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
#define inf (1<<29)
const int maxn = 110;
char s[maxn][maxn];
int mp[maxn][maxn];
bool is_s[maxn][maxn];
bool vis[maxn][maxn];
int dir[4][2] = {1,0,-1,0,0,1,0,-1};
struct node {
int x , y;
}a[12];
//node pre[maxn][maxn];
int n , m;
queue <node> q;
int ans;
bool inmap(int x,int y) {
return x >= 0 && x < n && y >= 0 && y < n;
}
bool check()
{
for(int i=0;i<=m+1;i++) {
int x = a[i].x , y = a[i].y;
if(mp[x][y] == -1) return false;
}
return true;
}
void debug_output(int id) {
printf("%d turn:\n" , id);
for(int i=0;i<n;i++) {
for(int j=0;j<n;j++) printf("%3d" , mp[i][j]);
puts("");
}
for(int i=0;i<=m+1;i++) {
printf("a[%d].x is %d , a[%d].y is %d\n",i,a[i].x,i,a[i].y);
}
}
void backtrack(int x,int y) {
if(mp[x][y] == 0) return;
int tmp = 1; if(is_s[x][y]) tmp += 1;
is_s[x][y] = false;
for(int i=0;i<4;i++) {
int xx = x + dir[i][0];
int yy = y + dir[i][1];
if(!inmap(xx,yy) || s[xx][yy] == '#') continue;
if(mp[xx][yy] + tmp == mp[x][y]) {
backtrack(xx,yy);
return;
}
}
return;
}
bool dfs(int id) {
//printf("check %d\n" , id);
memset(vis,false,sizeof(vis));
memset(mp,-1,sizeof(mp));
int x = a[id].x , y = a[id].y;
mp[x][y] = 0;
node u , v; u.x = x; u.y = y;
while(!q.empty()) q.pop();
q.push(u);
while(!q.empty()) {
u = q.front();
q.pop();
vis[u.x][u.y] = false;
for(int i=0;i<4;i++) {
x = u.x + dir[i][0];
y = u.y + dir[i][1];
if(!inmap(x,y) || s[x][y] == '#') continue;
int tmp = 1; if(is_s[x][y]) tmp += 1;
if(mp[x][y] == -1 || mp[x][y] > mp[u.x][u.y] + tmp) {
//pre[x][y].x = u.x;
//pre[x][y].y = u.y;
mp[x][y] = mp[u.x][u.y] + tmp;
if(!vis[x][y]) {
vis[x][y] = true;
v.x = x; v.y = y;
q.push(v);
}
}
}
}
debug_output(id);
if(id == 0 && !check()) return false;
ans += mp[ a[id+1].x ][ a[id+1].y ];
printf("tmp ans is %d\n" , ans);
if(id == m) return true;
backtrack(a[id+1].x , a[id+1].y);
dfs(id+1);
return true;
}
void init() {
for(int i=0;i<n;i++) scanf("%s" , s[i]);
memset(is_s,false,sizeof(is_s));
for(int i=0;i<n;i++) {
for(int j=0;j<n;j++) {
if(s[i][j] == 'K') { a[0].x = i; a[0].y = j; }
else if(s[i][j] == 'T') { a[m+1].x = i; a[m+1].y = j; }
else if(s[i][j] == 'S') { is_s[i][j] = true; }
else if(s[i][j] >= '1' && s[i][j] <= '9') {
int num = s[i][j] - '0';
a[num].x = i; a[num].y = j;
}
}
}
}
int main() {
while(~scanf("%d%d" , &n,&m) && n+m) {
init();
ans = 0;
if(!dfs(0)) puts("impossible");
else printf("%d\n" , ans);
}
return 0;
}
改进了之后还是wa了,下面是改成多把钥匙的wa的代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
#define inf (1<<29)
const int maxn = 110;
char s[maxn][maxn];
int mp[maxn][maxn];
bool is_s[maxn][maxn];
bool vis[maxn][maxn];
bool is_ss[maxn][maxn];
int dir[4][2] = {1,0,-1,0,0,1,0,-1};
struct node {
int x , y;
};
vector<node> a[12];
//node pre[maxn][maxn];
int n , m;
queue <node> q;
int ans;
bool inmap(int x,int y) {
return x >= 0 && x < n && y >= 0 && y < n;
}
bool check()
{
for(int i=0;i<=m+1;i++) {
bool ok = false;
int sz = a[i].size();
for(int j=0;j<sz;j++) {
int x = a[i][j].x , y = a[i][j].y;
if(mp[x][y] != -1) { ok = true; break; }
}
if(!ok) return false;
}
return true;
}
void backtrack(int x,int y) {
if(mp[x][y] == 0) return;
int tmp = 1; if(is_s[x][y]) tmp += 1;
is_s[x][y] = false;
for(int i=0;i<4;i++) {
int xx = x + dir[i][0];
int yy = y + dir[i][1];
if(!inmap(xx,yy) || s[xx][yy] == '#') continue;
if(mp[xx][yy] + tmp == mp[x][y]) {
backtrack(xx,yy);
return;
}
}
return;
}
/*
void gogo() {
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
is_ss[i][j] = is_s[i][j];
}
void backback() {
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
is_s[i][j] = is_ss[i][j];
}
*/
bool dfs(int id,int x,int y,int sum) {
//printf("id: %d , x:%d , y:%d , tmp sum: %d\n" , id,x,y,sum);
memset(vis,false,sizeof(vis));
memset(mp,-1,sizeof(mp));
mp[x][y] = 0;
node u , v; u.x = x; u.y = y;
while(!q.empty()) q.pop();
q.push(u);
while(!q.empty()) {
u = q.front();
q.pop();
vis[u.x][u.y] = false;
for(int i=0;i<4;i++) {
x = u.x + dir[i][0];
y = u.y + dir[i][1];
if(!inmap(x,y) || s[x][y] == '#') continue;
int tmp = 1; if(is_s[x][y]) tmp += 1;
if(mp[x][y] == -1 || mp[x][y] > mp[u.x][u.y] + tmp) {
//pre[x][y].x = u.x;
//pre[x][y].y = u.y;
mp[x][y] = mp[u.x][u.y] + tmp;
if(!vis[x][y]) {
vis[x][y] = true;
v.x = x; v.y = y;
q.push(v);
}
}
}
}
//debug_output(id);
if(id == 0 && !check()) return false;
if(id == m) {
int x = a[m+1][0].x , y = a[m+1][0].y;
if(sum + mp[x][y] < ans) ans = sum + mp[x][y];
return true;
}
int sz = a[id+1].size();
//gogo();
bool is_ss[maxn][maxn];
for(int i=0;i<n;i++) for(int j=0;j<n;j++) is_ss[i][j] = is_s[i][j];
for(int i=0;i<sz;i++) {
int x = a[id+1][i].x , y = a[id+1][i].y;
if(mp[x][y] == -1) continue;
backtrack(x , y);
dfs(id+1 , x , y , sum+mp[x][y]);
//backback();
for(int i=0;i<n;i++) for(int j=0;j<n;j++) is_s[i][j] = is_ss[i][j];
}
return true;
}
void init() {
for(int i=0;i<n;i++) scanf("%s" , s[i]);
memset(is_s,false,sizeof(is_s));
node u;
for(int i=0;i<=m+1;i++) a[i].clear();
for(int i=0;i<n;i++) {
for(int j=0;j<n;j++) {
if(s[i][j] == 'K') { u.x = i; u.y = j; a[0].push_back(u); }
else if(s[i][j] == 'T') { u.x = i; u.y = j; a[m+1].push_back(u); }
else if(s[i][j] == 'S') { is_s[i][j] = true; }
else if(s[i][j] >= '1' && s[i][j] <= '9') {
int num = s[i][j] - '0';
u.x = i; u.y = j;
a[num].push_back(u);
}
}
}
}
int main() {
while(~scanf("%d%d" , &n,&m) && n+m) {
init();
ans = inf;
if(!dfs(0 , a[0][0].x , a[0][0].y , 0)) puts("impossible");
else printf("%d\n" , ans);
}
return 0;
}
然后想用用dfs暴力吧,结果TLE了,下面是TLE的代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
#define inf (1<<29)
const int maxn = 110;
int dir[4][2] = {1,0,-1,0,0,1,0,-1};
char s[maxn][maxn];
int n , m;
int point[maxn][maxn] , vtime[maxn][maxn];
int ans;
int vis[12][maxn][maxn];
bool inmap(int x,int y) {
return x >= 0 && x < n && y >= 0 && y < n;
}
void dfs(int id,int x,int y , int step) {
//printf("id:%d , x:%d , y:%d , step:%d\n",id,x,y,step);
if(step >= ans) return;
if(id == m+1) {
if(step < ans) ans = step;
return;
}
for(int i=0;i<4;i++) {
int xx = x + dir[i][0] , yy = y + dir[i][1];
if(!inmap(xx , yy) || s[xx][yy] == '#' || vis[id][xx][yy] <= step) continue;
vis[id][xx][yy] = step;
if(point[xx][yy] == id+1) {
//memset(vis[id+1] , false , sizeof(vis[id+1]));
for(int j=0;j<n;j++)
for(int k=0;k<n;k++)
vis[id+1][j][k] = inf;
vis[id+1][xx][yy] = step+1;
dfs(id+1 , xx , yy , step+1);
for(int j=0;j<n;j++)
for(int k=0;k<n;k++)
if(s[j][k] == 'S' && vtime[j][k] > id) vtime[j][k] = inf;
}
else if(s[xx][yy] == 'S' && vtime[xx][yy] > id) {
vtime[xx][yy] = id;
dfs(id , xx , yy , step+2);
}
else {
dfs(id , xx , yy , step+1);
}
}
return;
}
int sx , sy;
void init() {
for(int i=0;i<n;i++) scanf("%s" , s[i]);
for(int i=0;i<n;i++)
for(int j=0;j<n;j++) {
if(s[i][j] == 'K') { sx = i; sy = j; point[i][j] = 0; }
else if(s[i][j] == 'T') { point[i][j] = m+1; }
else if(s[i][j] == 'S') { vtime[i][j] = inf; point[i][j] = -1; }
else if(s[i][j] >= '1' && s[i][j] <= '9') {
int num = s[i][j] - '0';
point[i][j] = num;
}
else point[i][j] = -1;
}
for(int i=0;i<=m+1;i++)
for(int j=0;j<n;j++)
for(int k=0;k<n;k++)
vis[i][j][k] = inf;
ans = inf;
}
//void before_bfs()
//bool before_check()
int main() {
while(~scanf("%d%d" , &n,&m) && n+m) {
init();
dfs(0,sx,sy,0);
if(ans == inf) puts("impossible");
else printf("%d\n" , ans);
}
return 0;
}
然后想想我这个老人应该省省了,明显就是贡献几个wa的人嘛!战斗了明显为负。
算了我还是回去安静的做一个美男子吧~
2014年9月30日补充:
后来在某一天晚上回去的路上碰到了12级最厉害的学弟LB,然后LB告诉了我他当时的做法是:枚举每一个有蛇的房间有没有走到,然后进行搜索。(不过走路有的时候不看人的毛病还是没有改过来,LB说他叫了我三四遍~然后我才发现我刚才是从他后面超过去的~~~竟然没看人真的是不好意思,不过也不能怪我,他不是萌妹子我没有太大兴趣~~)