洛谷 P1941 飛揚的小鳥 dp
阿新 • • 發佈:2018-12-20
思路:動態規劃,這裡下降的方程就是01揹包了,上升的由於到m之後還能繼續點保持m的高度,所以是完全揹包,但是由於同時只能執行一個,且若是先轉移01揹包的狀態會影響到後續完全揹包的轉移,所以優先轉移完全揹包,再轉移01揹包。
#include<cstdio> #include<iostream> #include<algorithm> #include<cmath> #include<cstring> #include<string> #include<map> #include<vector> #include<queue> #include<deque> using namespace std; #define ll long long #define PI acos(-1) #define INF 0x3f3f3f3f #define NUM 1005 #define debug true #define lowbit(x) ((-x)&x) #define ffor(i,d,u) for(int i=(d);i<=(u);++i) #define _ffor(i,u,d) for(int i=(u);i>=(d);--i) #define mst(array,Num,Kind,Count) memset(array,Num,sizeof(Kind)*(Count)) const int P = 1e9+7; int n,m,k; int x[10005],y[10005],num = 0; struct node { int l,h; }p[10005]; int dp[10005][1005]; int ans = INF; bool flag; template <typename T> void read(T& x) { x=0; char c;T t=1; while(((c=getchar())<'0'||c>'9')&&c!='-'); if(c=='-'){t=-1;c=getchar();} do(x*=10)+=(c-'0');while((c=getchar())>='0'&&c<='9'); x*=t; } template <typename T> void write(T x) { int len=0;char c[21]; if(x<0)putchar('-'),x*=(-1); do{++len;c[len]=(x%10)+'0';}while(x/=10); _ffor(i,len,1)putchar(c[i]); } void AC() { int pos; read(n),read(m),read(k); for(int i=0;i<n;++i)read(x[i]),read(y[i]); for(int i=0;i<=n;++i)p[i].l = 0,p[i].h = m+1; for(int i=1;i<=k;++i) { read(pos); read(p[pos].l),read(p[pos].h); } for(int i=1;i<=m;++i)dp[0][i] = 0; for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)dp[i][j] = INF; for(int i=0;i<n;++i) { flag = false; int k; for(int j=p[i].l+1;j<p[i].h;++j)//完全揹包 { if(p[i+1].h > m&&j+x[i] > m) dp[i+1][m] = min(dp[i+1][m],dp[i][j]+1); else if(j+x[i] < p[i+1].h) {//計算從i,j跳到i+1最少要點選幾次螢幕 if(j+x[i] <= p[i+1].l)k = (p[i+1].l-j)/x[i]+1; else k = 1; dp[i+1][j+k*x[i]] = min(dp[i+1][j+k*x[i]],dp[i][j]+k); } if(dp[i][j] != INF&&p[i].h <= m)flag = true; } for(int j=p[i+1].l+1;j<p[i+1].h;++j)//01揹包 { if(p[i+1].h > m&&j+x[i] > m) dp[i+1][m] = min(dp[i+1][m],dp[i+1][j]+1); else if(j+x[i] < p[i+1].h) dp[i+1][j+x[i]] = min(dp[i+1][j+x[i]],dp[i+1][j]+1); } for(int j=p[i].l+1;j<p[i].h;++j) if(j-y[i] > p[i+1].l)dp[i+1][j-y[i]] = min(dp[i+1][j-y[i]],dp[i][j]); if(flag)++num; } for(int i=p[n].l+1;i<p[n].h;++i)ans=min(ans,dp[n][i]); if(ans != INF)printf("1\n%d",ans); else printf("0\n%d",num); } int main() { AC(); return 0; }