題目鏈結
首先這是一道毒瘤題,寫了一下午沒有瞎弄出來,看了題解才有所領悟
以上都是一些廢話
分析
開始想過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 如果沒有改變,目前的這盆花肯定更優,雖然不加長度,但是要更新序列的...