你有乙個長方形的地圖,每乙個格仔要麼是乙個障礙物,要麼是乙個有一定價值的寶藏,要麼是乙個炸彈,或者是一塊空地。你的初始位置已經給出。
你每次可以走到上、下、左、右這四個相鄰的格仔。你不允許走出這幅地圖,不允許進入有寶藏、障礙物或是炸彈的地方。你需要規劃乙個閉合的路線(起點和終點都必須在初始位置)來取得寶藏。注意這個路線圍成的多邊形中不可以包含炸彈。假設路線圍成的多邊形包含的所有寶藏的價值之和為v,並且你從起點到終點走了 k
'>k步(從乙個格仔走到旁邊的格仔算作一步),那麼你沿該路線走一次將可以獲得v-k的利潤。
v'>k
'>v−k
'>
k'>你的任務是規劃乙個不包含炸彈的閉合路線,並可獲得最大的利潤。
k'>注意路線可以自交。為了確定乙個格仔是否在這條路線裡面,請使用以下演算法判斷:
1.假設該點的座標為需要判斷的點為 p(i,j) ,該點不在路線上
2.從該點往任意方向作一條射線,如果與路線相交奇數次,我們就認為這個格仔在這條路線裡面,否則這個格仔在這條路線外面。
k'>n,m<=20。炸彈和寶藏的個數總和不超過8個,保證只有1個初始點。
本題難點其實就是判斷格仔是否在路線裡面。(題目好良心系列)我選定的射線方向是豎直向上(當然其他方向也ok呀)。
所以,如果畫出路徑,所有的射線只會和橫向路徑相交(豎向的路徑就直接忽略啦)
對於每一小段橫向路徑(即點(x,y)到(x,y+1)),我們記錄這一小段路徑的右端點。如此以保證奇偶性正確。
5 — 4 —3
| |
6 9 2
| |
7 — 8 — 1
如圖,我們沿1-8尋找迴路,則被記錄的點有3,4,8,1。
雖然5和7沒有被記錄到,但這不影響9(多邊形內部)和多邊形外部的點的判斷。
(當然,如果是記錄所有橫向路徑的點也可以,例如記3,4,5,7,8,1;不過這就需要加些特判了)
#include#include#include
#include
using
namespace
std;
const
int n=21,k=8
;int f[4][2]=,,,};
int tx[10],ty[10
],cnt,k;
int n,m,sx,sy,w[10
];char mp[30][30
];int dp[23][23][1
int getx(int c)
int gety(int c)
int getz(int c)
intmain()
else
if (mp[i][j]>'
0'&&mp[i][j]<'9'
)
}k=cnt;
for (int i=1;i<=n;i++) for (int j=1;j<=m;j++)
if (mp[i][j]=='b'
)
for (int i=0;i"
%d",&w[i]);
memset(dp,
0x3f,sizeof
(dp));
dp[sx][sy][
0]=0
; q[
1]=num(sx,sy,0
); l=r=1
;
int_x,_y,_z,zz;
while (l<=r)}}
}bool _is;int ans=0
,sum,t;
for (int i=0;i<1
<)
if (_is) ans=max(ans,sum-dp[sx][sy][i]);
}cout
<}
2019 2 28 雜題選講
考慮將1至n m分別填入乙個擁有n行m列的 中,不允許重複。你需要滿足以下要求 第i行 1 i n 的最大值為ai。第j列 1 j m 的最大值為bj。請求出合法的填數方案數在模109 7意義下的值。1 n,m 1000 1 ai,bj n m 思路分步 填數 問題符合乘法原理,考慮從大到小填數,先...
雜題選講1 2
把序列排序後 問題轉化為子串行兩兩之間的異或和大於等於k 使用者 trie 樹優化 dp 因為不滿足單調性所以不能用二分來優化 從實際含義入手 ans n 2 sum d1 i dk i sum j k 線性預處理即可 複雜度 o n t 原先做 sa 的題時用過這個套路 列舉長度 len 2 每隔...
9 26雜題選講
非常開心,所有 都咕掉了 cy 簡單計數題,樹狀陣列維護即可。線段樹維護,如果乙個區間整除某個數的時候都等價於減同乙個數,那麼就打上區間減法的標記。複雜度玄學,但是能過。把正著做換成倒著做,把操作變成減去兩邊的數。考慮最大的那個數,顯然在它沒有變化的情況下兩邊的數都不能進行操作,所以如果它沒有變成目...