【BZOJ3749】Łasuchy
题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3749
很好的一道DP题,非常锻炼思维,难想的不得了。
定义dp[i][s]表示第i份食物的状态,0表示没有被选择,1表示被左边的人选择,2表示被右边的人选择,3表示被左右的人共同选择是否可行,若可行,则dp[i][s]表示i-1的状态。然后就可以进行转移了,对于每种状态的转移,都需要进行讨论,看是否满足条件,详见代码,建议画一下图,处理好条件。
然后,因为这是个成环的DP,最后一个位置还会反过来更新第一个位置,所以我们需要枚举第一个位置的状态,看是否可行。
1 #include <cstdio> 2 #include <cstring> 3 4 inline int get_num() { 5 int num = 0; 6 char c = getchar(); 7 while (c < '0' || c > '9') c = getchar(); 8 while (c >= '0' && c <= '9') 9 num = num * 10 + c - '0', c = getchar(); 10 return num; 11 } 12 13 const int maxn = 1e6 + 5; 14 15 int c[maxn], dp[maxn][4], ans[maxn]; 16 17 //~用于判断是否为-1 18 inline void mov(int pre, int now) { 19 if (~dp[pre][2] && c[pre] >= c[now]) dp[now][0] = 2; 20 else if (~dp[pre][3] && c[pre] >= c[now] * 2) dp[now][0] = 3; 21 if (~dp[pre][0] && c[pre] <= c[now]) dp[now][1] = 0; 22 else if (~dp[pre][1] && c[pre] <= c[now] * 2) dp[now][1] = 1; 23 if (~dp[pre][2] && c[pre] * 2 >= c[now]) dp[now][2] = 2; 24 else if (~dp[pre][3] && c[pre] >= c[now]) dp[now][2] = 3; 25 if (~dp[pre][0] && c[pre] * 2 <= c[now]) dp[now][3] = 0; 26 else if (~dp[pre][1] && c[pre] <= c[now]) dp[now][3] = 1; 27 } 28 29 int main() { 30 int n = get_num(); 31 for (int i = 1; i <= n; ++i) 32 c[i] = get_num(); 33 for (int s = 0; s < 4; ++s) { 34 memset(dp, -1, sizeof(dp)); 35 dp[1][s] = 4; 36 for (int j = 2; j <= n; ++j) mov(j - 1, j); 37 mov(n, 1); 38 if (dp[1][s] != 4) { 39 int p = dp[1][s]; 40 for (int i = n; i >= 1; --i) { 41 if (p == 1 || p == 3) ans[(i + n - 2) % n + 1] = i; 42 if (p == 2 || p == 3) ans[i] = i; 43 p = dp[i][p]; 44 } 45 for (int i = 1; i <= n; ++i) 46 printf("%d ", ans[i]); 47 return 0; 48 } 49 } 50 printf("NIE"); 51 return 0; 52 }