noip2013day2壓軸題 華容道

2021-08-28 03:50:14 字數 1747 閱讀 2862

題目鏈結

首先這是一道毒瘤題,寫了一下午沒有瞎弄出來,看了題解才有所領悟

以上都是一些廢話

分析

開始想過70分的暴力,直接暴力bfs,答案離線,起點相同的一起做;試過不止70分

首先很容易看出來這是一道圖論題,顯然是要用到最短路,確定d陣列狀態d[i][j][k]表示起點到(i,j),k方向是白塊的最短路徑,但是由於圖的特性,建圖,好像有點鬼畜,死磕2小時無所獲,於是果斷看題解

有乙個特點就是事實上移動棋子就是移動白塊;

格仔s想要走到與它相鄰的k方向(left,right,up,down)上的格仔,必須先把e格仔通過w的花費移到某個格仔,然後在用1的花費使s走到那 裡,總花費為w+1,由於從乙個格仔向相鄰方向上走一步的花費要多次使用,因此我們把它預處理成陣列a[x][y][k][h],表示從(x,y)這個棋子,白格仔在k方向上,使棋子走到h方向上相鄰的格仔的最少花費,這個可以用bfs預處理

然後就是最短路的過程,模板化,資料用spfa就能過,好吧我懶得寫dijkstra

答案在先處理就好了。**附注釋。

#include

#define up 1

#define down 2

#define left 3

#define right 4//方向

#define n 35

#define inf 0x3f3f3f3f

using

namespace

std;

struct node;//點狀態

int p[n][n],d[n][n][5],ex,ey,a[n][n][5][5],deep[n][n],n,m;

bool in[n][n][5],done[n][n];

queue

q,qb;

int other(int k) //相反方向移動

node go(node n,int k) //移動棋子

int bfs(node s,node t)}}

return deep[t.x][t.y];

}//基本寬搜操作

void init()//根據對稱性,加快效率

node t1=go((node),k);

node t2=go((node),h);

if(p[t1.x][t1.y]==0||p[t2.x][t2.y]==0)continue;//判斷固定點

a[i][j][k][h]=bfs(t1,t2)+1;//w+1的操作}}

p[i][j]=1;//恢復點的連通

}}int spfa(node s,node t));

in[s.x][s.y][k]=true;

d[s.x][s.y][k]=bfs((node),go(s,k));//計算白格仔到起點的步數

}//佇列初始化

p[s.x][s.y]=1;

while(!q.empty())

}//執行鬆弛操作}}

int res=inf;

for(int k=1;k<=4;k++)

res=min(res,d[t.x][t.y][k]);//得到答案

return res;

}int main(),(node));

if(ansprintf("%d\n",ans);

else

printf("-1\n");

return

0;}

Noip2013 Day2 T2 花匠(貪心)

花匠棟棟種了一排花,每株花都有自己的高度。花兒越長越大,也越來越擠。棟棟決定 把這排中的一部分花移走,將剩下的留在原地,使得剩下的花能有空間長大,同時,棟棟希 望剩下的花排列得比較別緻。具體而言,棟棟的花的高度可以看成一列整數h1,h2.hn。設當一部分花被移走後,剩下的花的高度依次為g1,g2.g...

Noip2013提高組day2 花匠

我們把原序列大概抽象在函式圖上,就會得出這樣的結果 如下圖 顯然,圈出來的點就是我們要保留的,不可能存在刪掉一大段會存在更優的情況。做法就是每次順著找乙個最高的點,再找乙個最低的點,如果存在相同的則視為乙個點。include include include define fo i,j,k for i...

NOIP2013提高組 day2 花匠

這道題是dp,但是寫錯了,還是貪心簡單,而且快 仔細觀察可以發現兩個條件其實意思就是這一排花最後要成波浪狀 那我們o n 跑一遍就好了,就像把目前的花接到序列中去 根據序列目前的上公升下降判斷長度是否有增加 如果改變了增減性,ans 如果沒有改變,目前的這盆花肯定更優,雖然不加長度,但是要更新序列的...