记录一个错误的正确!!!
我觉得归功于编译器
我要学编译原理!!!
问题是这样的
传送门:
https://www.luogu.org/problemnew/show/P4009
给定一个 N imes NN×N 的方形网格,设其左上角为起点◎,坐标(1,1)(1,1),XX 轴向右为正, YY 轴向下为正,每个方格边长为 1。
一辆汽车从起点◎出发驶向右下角终点▲,其坐标为 (N,N)(N,N)。
在若干个网格交叉点处,设置了油库,可供汽车在行驶途中加油。汽车在行驶过程中应遵守如下规则:
汽车只能沿网格边行驶,装满油后能行驶 KK 条网格边。出发时汽车已装满油,在起点与终点处不设油库。
汽车经过一条网格边时,若其 XX 坐标或 YY 坐标减小,则应付费用 BB ,否则免付费用。
汽车在行驶过程中遇油库则应加满油并付加油费用 AA。
在需要时可在网格点处增设油库,并付增设油库费用 CC(不含加油费用AA )。
N,K,A,B,CN,K,A,B,C 均为正整数, 且满足约束: 2leq Nleq 100,2 leq K leq 102≤N≤100,2≤K≤10。
设计一个算法,求出汽车从起点出发到达终点所付的最小费用。
这是一个我不是很会的题
后来了解到用BFS暴力可解
然后写了朴素的暴力广搜
#include<stdio.h>
typedef struct{
int x;
int y;
int fee;
int oil;
}Status;
int dir[4][3] = {{-1,0,0},{0,-1,0},{1,0,0},{0,1,0}};//←,↑,→,↓
int main(){
int N,K,A,B,C;
scanf("%d%d%d%d%d",&N,&K,&A,&B,&C);
dir[0][2] = dir[1][2] = B;//回退费用
char map[105][105]={0};
for(int i = 1;i<=N;i++){
for(int j = 1;j<=N;j++){
scanf("%d",&map[i][j]);
}
}
Status status[100000];
int left = 0, right = 0;
int tx, ty, tfee;
int minFee = 0x3f3f3f3f;
status[right++] = {1,1,0,K};//起始位置
while(left<=right){//BFS
Status t = status[left++];
if(t.x == N || t.y == N)continue;
for(int i = 0;i<4;i++){
tx = t.x+dir[i][0];
ty = t.y+dir[i][1];
if(tx == N && ty == N){//到达终点
minFee = t.fee>minFee?minFee:t.fee;
break;
}
if(tx<1||tx>N||ty<1||ty>N)continue;
status[right].x = tx;
status[right].y = ty;
status[right].oil = t.oil - 1;
tfee = t.fee+dir[i][2];//方向收费
if(map[tx][ty]==1){//加油站
tfee += A;
status[right].oil = K;
}else if(t.oil==1){//半路没油 前面保证(tx,ty)没到终点
tfee += C+A;
status[right].oil = K;
}
status[right++].fee = tfee;
}
}
printf("%d
",minFee);
return 0;
}
可以看到这里我忘记判断有没有形成环路
然而我在DEVC++中运行 居然可以得到正确结果!
稳定地得到正确结果
惊讶!一直不太相信的DEV环境居然能把这种优化掉
估计是爆数组后,程序就停下了。刚好最优结果存在。
我在VS里一直是死循环。。。
想半天没有想通为啥死循环,调试了才知道。。
I’m Vegetable. : (
2019/4/23
甚至第一版代码中
while(left<=right){}中
第一个if循环判断条件
if(t.x == N || t.y == N)
都写错了 应该是&&的
真不知道是怎么出正确结果的 摊手
更新正确答案
#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
typedef struct {
int x;
int y;
int fee;
int oil;
}Status;
int dir[4][3] = { {-1,0,0},{0,-1,0},{1,0,0},{0,1,0} };//←,↑,→,↓
int main() {
int N = 0, K = 0, A = 0, B = 0, C = 0;
scanf("%d%d%d%d%d", &N, &K, &A, &B, &C);
dir[0][2] = dir[1][2] = B;//回退费用
char map[105][105] = { 0 };
int mapOilFee[105][105][15];//一二维x, y, 第三维下标oil 值fee 记录较好状态下的油量与对应的费用 防止死循环
memset(mapOilFee, 0x3f, sizeof(mapOilFee));
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= N; j++) {
scanf("%d", &map[i][j]);
}
}
queue<Status> status;
int tx, ty, tfee;
int minFee = 0x3f3f3f3f;
Status t = { 1,1,0,K };
mapOilFee[1][1][K] = 0;//油量为K时fee==0
status.push(t);
while (status.size() != 0) {//BFS
t = status.front();
status.pop();
if (t.x == N && t.y == N)continue;
for (int i = 0; i < 4; i++) {
tx = t.x + dir[i][0];
ty = t.y + dir[i][1];
if (tx == N && ty == N) {//到达终点
minFee = t.fee > minFee ? minFee : t.fee;
break;
}
if (tx<1 || tx>N || ty<1 || ty>N)continue;
Status tem = { tx,ty,0,t.oil - 1 };
tfee = t.fee + dir[i][2];//方向收费
if (map[tx][ty] == 1) {//加油站
tfee += A;
tem.oil = K;
}
else if (t.oil == 1) {//半路没油 前面保证(tx,ty)没到终点
tfee += C + A;
tem.oil = K;
}
tem.fee = tfee;
if (tfee < mapOilFee[tx][ty][tem.oil]) {
status.push(tem);
mapOilFee[tx][ty][tem.oil] = tfee;
}
}
}
printf("%d", minFee);
return 0;
}
BFS暴力搜索每个状态
用队列优化空间复杂度
判断一定得不到最优解的提前结束
优化不够 会超时 会超时 会超时
2019/4/24