# re: 如何將動態規劃解決不了的問題轉化為判定性問題 回復 更多評論
2006-08-16 10:43 by
這位大哥..
偶是acm菜鳥...
你能給我講講pku 2738 的解題思路么..
email nsdy.wu@126.com
# re: 如何將動態規劃解決不了的問題轉化為判定性問題 回復 更多評論
2006-08-17 00:03 by
Nice to meet you here,
Very glad to share my ideas with you.
思維:
看到這題首先分析情形。初看似乎可以貪心,(偶WA了一次貪心).但是WA后,發現貪心出不了最優解(因為可能會有多組相同的解).
搜索顯然不行 ,1000的長度 + multiple test case => absolutely TLE.
于是考慮DP.
是否滿足最優子結構?恩。因為全局最優解包含局部最優解.
是否滿足無后效性? 恩。當前所作決策可由當前狀態唯一確定.
OK.DP.
首先是狀態.不用說,用d[i][j]表示當前i->j的最大可能值(即2號選手少的分)
接著是狀態轉移.d[i][j]可能是兩個方向轉過來的,即選了最前面一個或最后面一個.然后2nd player也應該會有一個相應的選擇.(具體見程序)
做好初始化的工作,就OK啦
Solution:
#include <stdio.h>
#include <string.h>
#include <math.h>
int a[1010], n, d[1010][1010];
int SecondDecision(int i, int j) //return which the Second player would like to get
{
if(a[i] >= a[j]) return i;
return j;
}
int Cal() //Dynamic Programming
{
int l, i, j, temp = 0;
for(i=1; i<n; i++)
d[i][i+1] = abs(a[i] - a[i+1]);
for(l = 4; l <= n; l += 2) //case length=2 has been calculated
for(i=1; i<=n-l+1; i++)
{
j = i+l-1;
if(SecondDecision(i+1, j) == j && d[i+1][j-1] >= 0)
{
temp = d[i+1][j-1] + a[i] - a[j];
d[i][j] = temp > d[i][j] ? temp : d[i][j];
}
else if(d[i+2][j] >= 0)
{
temp = d[i+2][j] + a[i] - a[i+1];
d[i][j] = temp > d[i][j] ? temp : d[i][j];
}
if(SecondDecision(i, j-1) == j-1 && d[i][j-2] >= 0)
{
temp = d[i][j-2] + a[j] - a[j-1];
d[i][j] = temp > d[i][j] ? temp : d[i][j];
}
else if(d[i+1][j-1] >= 0)
{
temp = d[i+1][j-1] + a[j] - a[i];
d[i][j] = temp > d[i][j] ? temp : d[i][j];
}
}
return d[1][n];
}
int main()
{
// freopen("ends.in", "r", stdin);
int i, ntc = 0;
while(scanf("%d", &n), n>0)
{
ntc++;
memset(a, 0, sizeof(a));
memset(d, -1, sizeof(d));
for(i=1; i<=n; i++)
scanf("%d", &a[i]);
printf("In game %d, the greedy strategy might lose by as many as %d points.\n", ntc, Cal());
}
return 0;
}
//代碼寫的不好 將就著看吧