标签:效率 pts lag inf clu 起点 阶段 algo pre
这道题我一看上去好像是搜索啊,但是发现起点和终点都有点多了吧。。。
然后我就懵圈了。
其实这道题是一个套着皮的背包dp。
其实用dp想,很多问题就简单了。比如多个起点,我初值都设为0就行了;多个终点,我都找一遍就行了。
我自己试着不看题解自己用传统dp的思路(不夹杂任何背包)来写,用暴力做的完全背包,也拿到了75pts。很感动。
我们设\(dp[i][j]\)为小鸟到达\(i\)行高度为\(j\)时的最少点击数。
小鸟一次可以点击多次,上升多次。也可以不点,下降一次。
可以抽象成向上的完全背包和向下的01背包。
所以如何优化其实都告诉你了:像优化背包问题那样去写这道题。
有几个细节要注意:
小鸟在高度为0处会死的。
小鸟在高度为\(m\)的时候再跳还是\(m\),在本来会跳出\(m\)的时候只会跳到\(m\)。
主要效率问题出现在完全背包的写法。
完全背包运用了这么一个思想:当前阶段的东西,可以由上一阶段装过来,还可以由现在阶段装过来。
所以在完全背包的时候写两句,一句针对上一阶段,一句针对当前阶段。也就是在这一秒多点击一次。
总的来说还是收获很多的。
代码:
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
const int maxn = 10002, maxm = 1002;
const int INF = 0x3f3f3f3f;
int up[maxn], down[maxn];
int upblock[maxn], downblock[maxn];
int dp[maxn][maxm];
bool have[maxn];
int n, m, t;
int main()
{
scanf("%d%d%d", &n, &m, &t);
for(int i = 0; i < n; i++)
{
scanf("%d%d", &up[i], &down[i]);
}
for(int i = 1; i <= t; i++)
{
int p, l, h; scanf("%d%d%d", &p, &l, &h);
upblock[p] = h; downblock[p] = l;
have[p] = true;
}
for(int i = 0; i <= n; i++)
{
if(!have[i])
{
downblock[i] = 0; upblock[i] = m + 1;
}
}
memset(dp, 0x3f, sizeof dp);
for(int i = 1; i <= m; i++) dp[0][i] = 0;
int cnt = 0; bool failed = false;
for(int i = 1; i <= n; i++)
{
for(int j = up[i - 1]; j <= m; j++)
{
if(j == m)
{
for(int k = m - up[i - 1]; k <= m; k++)
{
dp[i][j] = std::min(dp[i][j], dp[i - 1][k] + 1);
dp[i][j] = std::min(dp[i][j], dp[i][k] + 1);
}
}
dp[i][j] = std::min(dp[i][j], dp[i - 1][j - up[i - 1]] + 1);
dp[i][j] = std::min(dp[i][j], dp[i][j - up[i - 1]] + 1);
}
for(int j = downblock[i] + 1; j < upblock[i]; j++)
{
if(j + down[i - 1] >= upblock[i - 1] || j + down[i - 1] <= downblock[i - 1]) continue;
dp[i][j] = std::min(dp[i][j], dp[i - 1][j + down[i - 1]]);
}
for(int j = 1; j <= downblock[i]; j++) dp[i][j] = INF;
for(int j = upblock[i]; j <= m; j++) dp[i][j] = INF;
}
/*
int temp1, temp2;
while(scanf("%d%d", &temp1, &temp2) == 2 && temp1 != -1 && temp2 != -1)
{
printf("%d\n", dp[temp1][temp2]);
}
return 0;
*/
int ans = INF;
for(int i = 1; i <= m; i++) ans = std::min(ans, dp[n][i]);
if(ans != INF)
{
printf("1\n%d\n", ans);
}
else
{
int i, j;
bool flag = false;
for(i = n; i >= 1; i--)
{
for(j = 1; j <= m; j++)
{
if(dp[i][j] != INF)
{
flag = true;
break;
}
}
if(flag) break;
}
int cnt = 0;
for(int j = 1; j <= i; j++) if(have[j]) cnt++;
printf("0\n%d\n", cnt);
}
return 0;
}
标签:效率 pts lag inf clu 起点 阶段 algo pre
原文地址:https://www.cnblogs.com/Garen-Wang/p/9780994.html