2017NOIP 普及組T3 棋盤
棋盤
【問題描述】
有一個m × m的棋盤,棋盤上每一個格子可能是紅色、黃色或沒有任何顏色的。你現在 要從棋盤的最左上角走到棋盤的最右下角。
任何一個時刻,你所站在的位置必須是有顏色的(不能是無色的) ,你只能向上、下、 左、右四個方向前進。當你從一個格子走向另一個格子時,如果兩個格子的顏色相同,那你 不需要花費金幣;如果不同,則你需要花費 1 個金幣。
另外,你可以花費 2 個金幣施展魔法讓下一個無色格子暫時變為你指定的顏色。但這個 魔法不能連續使用,而且這個魔法的持續時間很短,也就是說,如果你使用了這個魔法,走 到了這個暫時有顏色的格子上,你就不能繼續使用魔法;只有當你離開這個位置,走到一個 本來就有顏色的格子上的時候,你才能繼續使用這個魔法,而當你離開了這個位置(施展魔 法使得變為有顏色的格子)時,這個格子恢復為無色。
現在你要從棋盤的最左上角,走到棋盤的最右下角,求花費的最少金幣是多少?
【輸入格式】
輸入檔名為 chess.in。
資料的第一行包含兩個正整數 m,n,以一個空格分開,分別代表棋盤的大小,棋盤上 有顏色的格子的數量。
接下來的 n 行,每行三個正整數 x,y,c,分別表示座標為(x,y)的格子有顏色 c。 其中 c=1 代表黃色,c=0 代表紅色。相鄰兩個數之間用一個空格隔開。
棋盤左上角的座標 為(1, 1),右下角的座標為(m, m)。 棋盤上其餘的格子都是無色。保證棋盤的左上角,也就是(1,1)一定是有顏色的。
【輸出格式】
輸出檔名為 chess.out。
輸出一行,一個整數,表示花費的金幣的最小值,如果無法到達,輸出-1。
【輸入輸出樣例 1】
input
5 7
1 1 0
1 2 0
2 2 1
3 3 1
3 4 0
4 4 1
5 5 0
output
8
見選手目錄下的 chess/chess1.in 和 chess/chess1.ans。
從(1,1)開始,走到(1,2)不花費金幣
從(1,2)向下走到(2,2)花費 1 枚金幣
從(2,2)施展魔法,將(2,3)變為黃色,花費 2 枚金幣
從(2,2)走到(2,3)不花費金幣
從(2,3)走到(3,3)不花費金幣
從(3,3)走到(3,4)花費 1 枚金幣
從(3,4)走到(4,4)花費 1 枚金幣
從(4,4)施展魔法,將(4,5)變為黃色,花費 2 枚金幣,
從(4,4)走到(4,5)不花費金幣
從(4,5)走到(5,5)花費 1 枚金幣
共花費 8 枚金幣。
【輸入輸出樣例 2】
input
5 5
1 1 0
1 2 0
2 2 1
3 3 1
5 5 0
output
-1
見選手目錄下的 chess/chess2.in 和 chess/chess2.ans。
【輸入輸出樣例 2 說明】
從(1,1)走到(1,2),不花費金幣
從(1,2)走到(2,2),花費 1 金幣
施展魔法將(2,3)變為黃色,並從(2,2)走到(2,3)花費 2 金幣
從(2,3)走到(3,3)不花費金幣
從(3,3)只能施展魔法到達(3,2),( 2,3),( 3,4),(4,3)
而從以上四點均無法到達(5,5),故無法到達終點,輸出-1
【輸入輸出樣例 3】
見選手目錄下的 chess/chess3.in 和 chess/chess3.ans。
【資料規模與約定】
對於 30%的資料,1 ≤ m ≤ 5, 1 ≤ n ≤ 10。
對於 60%的資料,1 ≤ m ≤ 20, 1 ≤ n ≤ 200。
對於 100%的資料,1 ≤ m ≤ 100, 1 ≤ n ≤ 1,000。
時間限制:1s
空間限制:256MB
解題思路:
就是dfs加上剪枝,實際上特別簡單,只需要四個方向都走一遍。就相當於暴搜。
程式碼:
#include <bits/stdc++.h>
using namespace std;
int color[102][102],cost[102][102];
int m,n;
void dfs(int x,int y,int pre_x,int pre_y,int pre_magic)
{
int magic=0,tmp_cost,tmp_color;
if(x==0||y==0||x==m+1||y==m+1)
return;
if(pre_magic==1&&color[x][y]==-1)
return;
if(pre_magic==0&&color[x][y]!=-1)
{
if(color[x][y]!=color[pre_x][pre_y])
tmp_cost=cost[pre_x][pre_y]+1;
else
tmp_cost=cost[pre_x][pre_y];
}
else if(color[x][y]==-1&&pre_magic==0)
{
magic=1;
tmp_cost=cost[pre_x][pre_y]+2;
}
else if(pre_magic==1&&color[x][y]!=-1)
{
if(color[x][y]!=color[pre_x][pre_y])
tmp_cost=cost[pre_x][pre_y]+1;
else
tmp_cost=cost[pre_x][pre_y];
}
if(cost[x][y]!=-1&&tmp_cost>=cost[x][y])
return;
cost[x][y]=tmp_cost;
if(magic==1)
color[x][y]=color[pre_x][pre_y];
if(pre_magic==1)
{
tmp_color=color[pre_x][pre_y];
color[pre_x][pre_y]=-1;
}
dfs(x+1,y,x,y,magic);
dfs(x-1,y,x,y,magic);
dfs(x,y+1,x,y,magic);
dfs(x,y-1,x,y,magic);
if(magic==1)
color[x][y]=-1;
if(pre_magic==1)
color[pre_x][pre_y]=tmp_color;
}
int main()
{
int i,j,x,y,c;
scanf("%d %d",&m,&n);
memset(cost,0xff,sizeof(cost));
memset(color,0xff,sizeof(color));
cost[1][1]=0;
for(i=0;i<n;i++)
{
scanf("%d %d %d",&x,&y,&c);
color[x][y]=c;
}
dfs(1,2,1,1,0);
dfs(2,1,1,1,0);
printf("%d",cost[m][m]);
return 0;
}