題目傳送門
【題目大意】
一天由$n$個小時構成,在第$i$個小時睡覺能夠恢復$u_i$點體力。有一頭牛要休息$b$個小時,可以不連續,但休息的第1個小時無法恢復體力。前一天的最後乙個小時和第二天的第乙個小時是連在一起的,求這頭牛能恢復的體力最大值。
【思路解析】
首先這是乙個環形dp問題,所以我們先簡化問題,假設前一天的最後乙個小時和第二天的第乙個小時不是連在一起的,轉化為線性問題來處理。設$f[i][j][1]$表示前$i$個小時休息了$j$個小時,並且第$i$個小時在休息的體力恢復最大值,$f[i][j][0]$則表示第$i$個小時不休息的體力恢復最大值。於是可以得到轉移方程:
$$f[i][j][1]=max(f[i-1][j-1][0],f[i-1][j-1][1]+u[i])$$
$$f[i][j][0]=max(f[i-1][j][0],f[i-1][j][1])$$
初始值:$f[1][0][0]=f[1][1][1]=0$,其餘為負無窮
目標:$max(f[n][b][0],f[n][b][1])$
然後我們考慮前一天的最後乙個小時和第二天的第乙個小時連在一起的情況,只需要把初始值改為$f[1][1][1]=u_1$,其餘為負無窮,再跑一遍dp,然後答案為$f[n][b][1]$(為了保證第乙個小時能恢復體力,前一天的最後乙個小時必須休息)。
【**實現】
1 #include2 #include3 #include4**戳這裡#define rg register
5#define go(i,a,b) for(rg int i=a;i<=b;i++)
6#define back(i,a,b) for(rg int i=a;i>=b;i--)
7#define mem(a) memset(a,128,sizeof(a));
8using
namespace
std;
9const
int n=3832;10
const
int inf=1e9+9;11
int n,b,u[n],f[n][2],ans=-inf;
12int
main()
20 ans=max(f[b][1],f[b][0
]);21 mem(f);f[1][1]=u[1
];22 go(i,2,n) back(j,min(i,b),1
)26 ans=max(ans,f[b][1
]);27 printf("
%d\n
",ans);
28return0;
29 }
POJ 2228 Naptime(DP 環形處理)
這題一眼望去dp。發現自己太智障了。這題想的是o n 3m 的。環形處理只會斷環成鏈。然後dp也想的不好。我們先考慮如果除去環這題該怎麼做?dp i j 0 1 代表到第i小時睡了j個小時,第i小時睡了 沒睡權值最大值。初值dp 1 1 1 dp 1 0 0 0 dp i 0 0 0 其餘都是負無窮...
POJ 刷題順序
poj從簡到難 按照ac數目排序 的列表如下,作為小弱的刷題順序。大牛們可以看後面倒排的hard表,還有四道題沒人拿到first blood.屬性依次為 id,title,ratio,ac,submit hard模式 4027 flights 0.0 0 39 4029 huzita axiom 6...
POJ 水題若干
poj 3176 cow bowling 這道題可以算是dp入門吧。可以用乙個二維陣列從下向上來搜尋從而得到最大值。優化之後可以直接用一維陣列來存。ps 用一維的時候要好好想想具體應該怎麼存,還是有技巧的 include include include includeusing namespace ...