当前位置: 代码迷 >> 综合 >> POJ1065 Wooden Sticks(贪心||DP)
  详细解决方案

POJ1065 Wooden Sticks(贪心||DP)

热度:51   发布时间:2024-01-16 13:39:14.0

题意:

一些有长度l和重量w的木棍要装在机器上,如果前一个木棍长度和重量均小于等于当前木棍,装上机器不耗时,否则时间+1,问全装上最少时间。

要点:

可以用贪心或DP,贪心就是先按长度从小到大排好,再根据重量,用一个d数组标记是否用过,从一根木棍出发,往后找重量大于等于它的木棍,将它的d标记为1,再以这个新木棍为起点再往后找,遍历一遍后再从d为0的木棍出发,看能遍历几次就是最小时间。


贪心:

15583101 Seasonal 1065 Accepted 224K 16MS C++ 822B 2016-06-02 15:32:11
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<algorithm>
using namespace std;
struct node
{int l, w;
}a[5005];
int d[5005];bool cmp(node a, node b)
{if (a.l == b.l)return a.w < b.w;return a.l < b.l;
}int main()
{int t,n,i;scanf("%d", &t);while (t--){scanf("%d", &n);for (i = 0; i < n; i++)scanf("%d%d", &a[i].l, &a[i].w);sort(a, a + n, cmp);memset(d, 0, sizeof(d));int ans = 0;while (1){bool flag = true;int temp;for (i = 0; i < n; i++)if (d[i] == 0){temp = i;d[i] = 1;flag = false;ans++;break;}if (flag)break;for (i = 0; i < n; i++){if (!d[i] && a[temp].l <= a[i].l&&a[temp].w <= a[i].w){temp = i;d[i] = 1;}}}printf("%d\n", ans);}return 0;
}

DP(偏序定理):

这题用DP需要用到偏序定理,看不太懂,应用到这题就是,按l从小到大排好后,求有几个最大不下降子序列,那么这里运用偏序定理可以知道,有几个最大不下降子序列等于最大下降子序列中的元素个数,具体证明是用鸽笼原理,看的半懂不懂的,下学期学一下离散数学再看看吧。
偏序定理: 点击打开链接
鸽笼原理证明: 点击打开链接
15583207 Seasonal 1065 Accepted 224K 110MS C++ 658B 2016-06-02 15:52:25
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<algorithm>
using namespace std;
struct node
{int l, w;
}a[5005];
int dp[5005];bool cmp(node a, node b)
{if (a.l == b.l)return a.w < b.w;return a.l < b.l;
}int main()
{int t,n,i,j;scanf("%d", &t);while (t--){scanf("%d", &n);for (i = 0; i < n; i++)scanf("%d%d", &a[i].l, &a[i].w);sort(a, a + n, cmp);for (i = 0; i < n; i++)dp[i] = 1;for (i = 0; i < n; i++)for (j = 0; j < i; j++)if (a[i].w < a[j].w)//求最长下降序列dp[i] = max(dp[i], dp[j] + 1);int ans = -1;for (i = 0; i < n; i++)ans = max(ans, dp[i]);printf("%d\n", ans);}return 0;
}