20201104gryz模擬賽解題報告
阿新 • • 發佈:2020-11-04
寫在前面
\(Luckyblock\) 良心出題人,
題面好評
T1還是蠻簡單的,用一個棧來維護就能過(某天聽說 \(Luckyblock\) 出了套題,T1是個考棧的,看來就是這道了
注:棧的清空只需要把 \(top\) 置為 \(0\) 即可,沒必要用 \(memset\)
T2一開始打算單調棧+字首和求驚喜度,但小數模法並不會,因此沒寫,暴力也不會打,看到正解後考慮到我的解法可能會被卡
T3暴力不知道為啥寫掛了
T4輸入的時候沒讀題,輸入的 \(x\) 和 \(y\) 多打了一組,所以 \(10\) 也沒騙到,後面 \(2h\) 一直在推DP式
T1 大空魔術
簡述題意:
給你一串由 \(A\)
\(Solution\):
發現 \(?B\) 是可以對毀的,考慮開一個棧,每讀到一個元素,和棧頂元素比較,如果棧頂元素是 \(A\) 或 \(B\) 且讀到元素是 \(B\) ,就彈出棧頂元素,否則放入棧中,最後輸出棧內元素個數
正確性:發現 \(B\) 與誰都能對毀,因此在前面對毀的越多,對結果越有利
/* Work by: Suzt_ilymics Knowledge: ?? Time: O(??) =============================Luckyblock AK IOI=========================================== */ #include<iostream> #include<cstdio> #include<cstring> #include<string> using namespace std; const int MAXN = 2e6+6; int T, n; char stc[MAXN]; int top = 0; string s; int main() { // freopen("a.in","r",stdin); // freopen("a.out","w",stdout); scanf("%d", &T); while(T--){ top = 0; cin>>s; int len = s.size(); for(int i = 0; i < len; ++i){ if((stc[top] == 'A' && s[i] == 'B') || (stc[top] == 'B' && s[i] == 'B')){ top--; } else{ stc[++top] = s[i]; } } printf("%d\n", top); } return 0; }
T4 萃香抱西瓜
簡述題意:簡化不動
\(Solution\):
稍有點細節的狀壓 DP。
讀入時對所有時刻所有位置進行標記,記錄是否有大小西瓜。
發現小西瓜個數較小,考慮狀壓一下獲得的小西瓜狀態。
設 \(s_{t,x,y}\) 表示 \(t\) 時刻,位置 \((x,y)\) 的小西瓜的存在狀態。
設 \(f(t,x,y,S)\) 表示,在時間 \(t\),萃香的位置在 \((x,y)\),獲得的小西瓜狀態為 \(S\) 時,需要移動的最小步數。
初始化 \(f(1,sx,sy,s1,sx,sy)=0\),所有不可到達狀態的 \(f=Inf\)。
轉移時列舉每個時刻每個位置,從能到達該位置的上個時刻的位置 \((x′,y′)\)
\(f(t,x,y,S|s_{t,x,y})=min{f(t−1,x′,y′,S)}+1\)
統計答案時列舉最後一個時刻的所有取完所有小西瓜的狀態,取最小值即可。
複雜度 \(O(Thw2^m)\),資料範圍小可以隨便過。
不是很懂,所以直接搬的題解(逃
(Luckyblock變數名好評
/*
Work by: Suzt_ilymics
Knowledge: ??
Time: O(??)
*/
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int MAXALL = 0x3f3f3f3f;
const int kMAX = (1 << 10) + 1;
int dx[5] = {0, 0, 0, 1, -1};
int dy[5] = {0, 1, -1, 0, 0};
int h, w, T, sx, sy;
int n, m, sum = 0;
int a[6][6][110];
int f[6][6][110][kMAX];
int read(){
int w = 1, s = 0;
char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') w = -1; ch = getchar(); }
while(ch >= '0' && ch <= '9') s = (s << 1) + (s << 3) + ch - '0', ch = getchar();
return s * w;
}
int main()
{
// freopen("d.in","r",stdin);
// freopen("d.out","w",stdout);
h = read(), w = read(), T = read(), sx = read(), sy = read();
n = read(), m = read();
for(int i = 1, t1_ = 0, t2_ = 0, a_ = 0; i <= n; ++i){
t1_ = read(), t2_ = read(), a_ = read();
if(a_) sum++;
for(int j = t1_, x, y; j < t2_; ++j){
x = read(), y = read();
if(a_ == 0){ a[x][y][j] = -1; }
else{ a[x][y][j] = (1 << (sum - 1)); }
}
}
if(a[sx][sy][1] == -1) {
printf("-1"); return 0;
}
int all = (1 << m) - 1;
memset(f, 0x3f, sizeof(f));
f[sx][sy][1][a[sx][sy][1]] = 0;//初始化
for(int i = 2; i <= T; ++i){
for(int x = 1; x <= w; ++x){
for(int y = 1; y <= h; ++y){
if(a[x][y][i] == -1) continue;
for(int fx = 0; fx <= 4; ++fx){
int x_ = x + dx[fx], y_ = y + dy[fx];
if(x_ < 1 || x_ > w || y_ < 1 || y_ > h) continue;
if(a[x_][y_][i - 1] == -1) continue;
for(int k = 0; k <= all; ++k){
f[x][y][i][k | a[x][y][i]] = min(f[x][y][i][k | a[x][y][i]], f[x_][y_][i -1][k] + (fx > 0));
}
}
}
}
}
int ans = f[0][0][0][0];
for(int x = 1; x <= w; ++x){
for(int y = 1; y <= h; ++y){
ans = min(ans, f[x][y][T][all]);
}
}
printf("%d\n", ans < MAXALL ? ans : -1);
return 0;
}