[vijos1907][codevs3729]飞扬的小鸟
2017-10-26 16:37
183 查看
题目←
n <= 10000,m <= 1000,凑成10^7刚好
所以设dp[i][j]为到位置i高度j的最小步数
一个显然的转移是dp[i][j] = min(dp[i - 1][j - h[i][0]],dp[i - 1][j +h[i][1])
然而我们注意到,在一个地方只是可以多次点击的
也就是说,h[i][0]可以累加多次
枚举h[i][0]累加次数会T两个点
但我们注意到,一个物品可以无限选,这点特性很像完全背包
所以顺推j,dp[i][j]从dp[i][j - h[i][0]]转移过来,相当于升高了多次h[i][0]
鉴于某一位置即便不合法(撞管子),我们也许还要使用该状态做转移(同一位置多次点击),所以在同一位置所有高度都处理完成后再判断是否合法。
一开始没有判断点击一次不合法而多次合法的情况
打了个卵都不对的程序结果水了80……
n <= 10000,m <= 1000,凑成10^7刚好
所以设dp[i][j]为到位置i高度j的最小步数
一个显然的转移是dp[i][j] = min(dp[i - 1][j - h[i][0]],dp[i - 1][j +h[i][1])
然而我们注意到,在一个地方只是可以多次点击的
也就是说,h[i][0]可以累加多次
枚举h[i][0]累加次数会T两个点
但我们注意到,一个物品可以无限选,这点特性很像完全背包
所以顺推j,dp[i][j]从dp[i][j - h[i][0]]转移过来,相当于升高了多次h[i][0]
鉴于某一位置即便不合法(撞管子),我们也许还要使用该状态做转移(同一位置多次点击),所以在同一位置所有高度都处理完成后再判断是否合法。
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #define INF 1061109567 using namespace std; const int MAXN = 10000 + 50; int n,m,k,x,y,z; int xz[MAXN][2],h[MAXN][2]; int dp[MAXN][1050]; bool ch; int ans; int num[MAXN]; int step = INF; bool can(int pos,int H){ if(H > xz[pos][0] && H < xz[pos][1])return true; return false; } struct zt{ int z,d,u; }l[MAXN << 1]; bool cmp(zt a,zt b){ return a.z < b.z; } int main(){ scanf("%d%d%d",&n,&m,&k); for(int i = 0;i < n;i ++){ scanf("%d%d",&h[i + 1][0],&h[i + 1][1]); xz[i][0] = 0;xz[i][1] = m + 1; } xz [0] = 0;xz [1] = m + 1; for(int i = 1;i <= k;i ++){ scanf("%d%d%d",&l[i].z,&l[i].d,&l[i].u); } sort(l + 1,l + k + 1,cmp); for(int i = 1;i <= k;i ++){ xz[l[i].z][0] = l[i].d; xz[l[i].z][1] = l[i].u; num[l[i].z] ++; } for(int i = 0;i <= n;i ++){ num[i] += num[i - 1]; } memset(dp,0x3f,sizeof(dp)); for(int i = 0;i <= m;i ++) dp[0][i] = 0; for(int i = 1;i <= n;i ++){ for(int j = h[i][0] + 1;j <= m;j ++){ if(j - h[i][0] >= 0){ dp[i][j] = min(dp[i][j],dp[i - 1][j - h[i][0]] + 1); dp[i][j] = min(dp[i][j],dp[i][j - h[i][0]] + 1); } if(j == m){ for(int k = j - h[i][0];k <= m;k ++){ dp[i][j] = min(dp[i][j],dp[i - 1][k] + 1); dp[i][j] = min(dp[i][j],dp[i][k] + 1); } } } for(int j = m;j >= 0;j --){ if(j && j + h[i][1] <= m && can(i - 1,j + h[i][1]) && can(i,j)){ dp[i][j] = min(dp[i][j],dp[i - 1][j + h[i][1]]); } if(!can(i,j))dp[i][j] = INF; if(dp[i][j] != INF)ans = max(ans,i); } if(ans != i)break; } for(int i = 0;i <= m;i ++){ step = min(step,dp [i]); } if(step == INF){ printf("%d\n%d",0,num[ans]); } else { printf("1\n%d",step); } }
一开始没有判断点击一次不合法而多次合法的情况
打了个卵都不对的程序结果水了80……
相关文章推荐
- 【uoj #17】【codevs3729】【luogu1941】【NOIP2014】飞扬的小鸟
- 【uoj #17】【codevs3729】【luogu1941】【NOIP2014】飞扬的小鸟
- CODE[VS] 3729 飞扬的小鸟 背包
- 飞扬的小鸟(codevs 3729)
- Codevs 3729==洛谷P1941 飞扬的小鸟
- codevs3729: [NOIP2014]飞扬的小鸟
- vijos1907[noip2014]飞扬的小鸟(完全背包)
- vijos1907[noip2014]飞扬的小鸟(完全背包)
- codevs 3729 飞扬的小鸟
- Codevs 3729 飞扬的小鸟
- CODE[VS] 1475 m进制转十进制
- codevs 1083Cantor表
- NOIP 2014(COGS 1805) 飞扬的小鸟 完全背包
- Ubuntu中修改vscode中默认python版本
- BFS搜索算法应用_Codevs 1004 四子连棋
- xor和路径(codevs 2412)
- [codevs1135]选择客栈
- 控制公司(codevs 2051)
- 欢迎使用 FreeCode for VS60/VS2005 Add-in
- CODE[VS]1027 姓名与ID