【題解】LuoGu1941:飛揚的小鳥

原題傳送門
此題暴力dp可過
dpi,jdp_{i,j}表示到(i,j)(i,j)的最小點擊數

非常naivenaive的轉移方程
dpi,j=min(dpi1,jxi,dpi,jxi)+1dp_{i,j}=min(dp_{i-1,j-x_i},dp_{i,j-x_i})+1
dpi,j=min(dpi,j,dpi1,j+yi)dp_{i,j}=min(dp_{i,j},dp_{i-1,j+y_i})
jj的枚舉順序注意一下,第一個的完全揹包,第二個是01揹包
另外,注意一下往上突破天花板的特殊情況
dpi,m=min(dpi,m,dpi,j)(m<j<=m+xi)dp_{i,m}=min(dp_{i,m},dp_{i,j})(m<j<=m+x_i)

是否到達終點隨便判斷一下就好了

Code:

#include <bits/stdc++.h>
#define maxn 10010
using namespace std;
int n, m, k, x[maxn], y[maxn], L[maxn], H[maxn], dp[maxn][2010], flag[maxn];

inline int read(){
	int s = 0, w = 1;
	char c = getchar();
	for (; !isdigit(c); c = getchar()) if (c == '-') w = -1;
	for (; isdigit(c); c = getchar()) s = (s << 1) + (s << 3) + (c ^ 48);
	return s * w;
}

int main(){
	n = read(), m = read(), k = read();
	for (int i = 1; i <= n; ++i) x[i] = read(), y[i] = read(), H[i] = m + 1;
	int p;
	for (int i = 1; i <= k; ++i) p = read(), L[p] = read(), H[p] = read(), flag[p] = 1;
	memset(dp, 0x3f, sizeof(dp));
	for (int i = 1; i <= m; ++i) dp[0][i] = 0;
	for (int i = 1; i <= n; ++i){
		for (int j = x[i] + 1; j <= m + x[i]; ++j) dp[i][j] = min(dp[i - 1][j - x[i]], dp[i][j - x[i]]) + 1;
		for (int j = m + 1; j <= m + x[i]; ++j) dp[i][m] = min(dp[i][m], dp[i][j]);
		for (int j = 1; j <= m - y[i]; ++j) dp[i][j] = min(dp[i][j], dp[i - 1][j + y[i]]);
		for (int j = 1; j <= L[i]; ++j) dp[i][j] = dp[0][0];
		for (int j = H[i]; j <= m; ++j) dp[i][j] = dp[0][0];
	}
	int ans = dp[0][0];
	for (int i = 1; i <= m; ++i) ans = min(ans, dp[n][i]);
	if (ans < dp[0][0]) printf("1\n%d\n", ans); else{
		int ans = 0;
		for (int i = n; i; --i){
			int s = dp[0][0];
			for (int j = 1; j <= m; ++j) s = min(s, dp[i][j]);
			if (s < dp[0][0]) break;
			ans += flag[i];
		}
		printf("0\n%d\n", k - ans);
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章