hgoi#2019/2/16--t3--psolve
阿新 • • 發佈:2019-02-16
pso 解法 做出 難題 狀態 %d i++ ax1 所有
題目描述
Dustar有n道題目要做。他的月薪是m元。
由於題目是一流的難題,所以Dustar不得不找個人來幫(代)助(替)他寫作業。
找人寫作業不是免費的,但是他們能保證在一個月內做出任何題目。每做一道題需要兩筆付款,第一筆ai元在做題的那一個月初支付,第二筆b[i]元(1<=b[i]<=m)在做完後的下一個月初支付。每一個月Dustar用上一個月掙的錢來付款。
Dustar沒有任何存款意識,所以每個月的節余都回拿用去買糖吃掉了。
因為題目是相互關聯的,它們必須按順序解出。比如,題目3必須在題目4之前或同一個月解出。
請問做完所有題目並支付完所有款項的最少月數。
解法
第一眼看到這道題會想到貪心,如果當前可以放到下一個月裏去,但是這樣很明顯是錯的。。。
試試這組數據
10 9
1 9
9 1
這樣就會被卡住,那麽怎麽做?
那麽就是DP。我們設置\(f[i][j]\)表示到第\(i\)天買了\(j\)物品的答案。
我們每次看一下前後天是否滿足狀態就好了。
ac代碼
#include<bits/stdc++.h> #define N 305 using namespace std; int f[N][N],a[N],b[N]; int n,m; int r(){ int w=0,x=0;char ch=0; while(!isdigit(ch))w|=ch=='-',ch=getchar(); while(isdigit(ch))x=(x<<1)+(x<<3)+(ch^48),ch=getchar(); return w?-x:x; } int main(){ m=r(),n=r(); for(int i=1;i<=n;i++)a[i]=r(),b[i]=r(); memset(f,-1,sizeof(f)); f[1][0]=m; for(int i=1;i<=n;i++){ for(int j=0;j<=n;j++) { if(f[i][j]<0) break; int res1=f[i][j],res2=m; f[i+1][j]=max(f[i+1][j],m); for(int k=j+1;k<=n;k++){ if(res1-a[k]<0||res2-b[k]<0) break; res1-=a[k],res2-=b[k]; f[i+1][k]=max(f[i+1][k],res2); } } } int ans; for(int i=1;i<=2*n;i++){ if(f[i][n]!=-1){ans=i;break;} } printf("%d\n",ans+1); return 0; }
hgoi#2019/2/16--t3--psolve