Garlands UVA

来源:互联网 发布:js除法取整不四舍五入 编辑:程序博客网 时间:2024/06/06 02:01

首先特殊判断一下所给出的数据是否能够得到我们想要的最终结果,如果可以,那么就开始进行动态规划的过程:记录所拥有的物品质量之和,然后二分法开始判断,对于选定的质量假设为amount是否能够保证在满足题意的条件下得到相应的解。dp[i][j]表示的是目前利用i个灯泡能够得到的在所有半段的最重的重量不超过amount的时候所得到的段的个数。其中为了便于后续状态更加方便的转移,使用j来标志当前所拥有的段的个数是奇数个还是偶数个,0对应偶数,1对应奇数,然后让i从2开始增加,每次增加的步长为2(依据题意得到的)。对于每一个i找出我们所能进行添加灯的方案的最小值,并且记录,作为后面的参照,最后比较即可,具体实现见如下代码:

#include<iostream>#include<vector>#include<string>#include<set>#include<stack>#include<queue>#include<map>#include<algorithm>#include<cmath>#include<iomanip>#include<cstring>#include<sstream>#include<cstdio>#include<deque>using namespace std;class Solve{public:int n, m, d;int data[40005], sum[40005];void Init(){sum[0] = 0;for (int i = 1; i <= n; i++){cin >> data[i];sum[i] = sum[i - 1] + data[i];}}bool DP(int amount){int dp[40005][2];int INF = 1 << 30;dp[0][0] = 0;dp[0][1] = INF;for (int i = 2; i <= n; i += 2){dp[i][0] = INF;dp[i][1] = INF;for (int len = 1; len <= d&&i - len * 2 >= 0; len++){if (sum[i] - sum[i - len] > amount) break;if (sum[i - len] - sum[i - 2 * len] <= amount){dp[i][0] = min(dp[i][0], dp[i - 2 * len][1] + 1);dp[i][1] = min(dp[i][1], dp[i - 2 * len][0] + 1);}}}if (dp[n][(m - 1) % 2] > m - 1) return false;return true;}void Deal(){Init();int left = 1, right = sum[n];if ((m-1)*2*d<n||n%2||n<2*(m-1)){cout << "BAD" << endl;return;}while (left < right){int mid = (left + right) / 2;if (!DP(mid)) left = mid + 1;else right = mid;}cout << left << endl;}};int main(){int Z;cin >> Z;Solve a;while (Z--){cin >> a.n >> a.m >> a.d;a.Deal();}}

原创粉丝点击