Wooden Sticks
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 26050 | Accepted: 11277 |
Description
There is a pile of n wooden sticks. The length and weight of each stick are known in advance. The sticks are to be processed by a woodworking machine in one by one fashion. It needs some time, called setup time, for the machine to prepare processing a stick. The setup times are associated with cleaning operations and changing tools and shapes in the machine. The setup times of the woodworking machine are given as follows:
(a) The setup time for the first wooden stick is 1 minute.
(b) Right after processing a stick of length l and weight w , the machine will need no setup time for a stick of length l' and weight w' if l <= l' and w <= w'. Otherwise, it will need 1 minute for setup.
You are to find the minimum setup time to process a given pile of n wooden sticks. For example, if you have five sticks whose pairs of length and weight are ( 9 , 4 ) , ( 2 , 5 ) , ( 1 , 2 ) , ( 5 , 3 ) , and ( 4 , 1 ) , then the minimum setup time should be 2 minutes since there is a sequence of pairs ( 4 , 1 ) , ( 5 , 3 ) , ( 9 , 4 ) , ( 1 , 2 ) , ( 2 , 5 ) .
Input
The input consists of T test cases. The number of test cases (T) is given in the first line of the input file. Each test case consists of two lines: The first line has an integer n , 1 <= n <= 5000 , that represents the number of wooden sticks in the test case, and the second line contains 2n positive integers l1 , w1 , l2 , w2 ,..., ln , wn , each of magnitude at most 10000 , where li and wi are the length and weight of the i th wooden stick, respectively. The 2n integers are delimited by one or more spaces.
Output
The output should contain the minimum setup time in minutes, one per line.
Sample Input
3
5
4 9 5 2 2 1 3 5 1 4
3
2 2 1 1 2 2
3
1 3 2 2 3 1
Sample Output
2
1
3
Source
附赠一组数据
7
4
85 74 56 25 10 30 98 81
2
53 28 34 59
6
35 82 57 36 5 2 84 40 44 58 87 19
6
66 78 60 35 51 72 34 56 98 78 33 100
3
22 62 7 22 59 59
9
38 63 69 75 90 35 33 77 77 74 42 84 10 55 72 40 29 36
8
51 24 23 24 35 20 79 32 79 58 37 14 86 10 16 36
answer
2
2
4
3
2
4
5
开始写了一段贪心的代码,先附上作为反例吧
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
struct node{
int l,w;
bool operator < (const node &a)const{
if(a.l==l)
return a.w>w;
return a.l>l;
}
}num[5002];
int dp[5002];
const int INF=0x3f3f3f3f;
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define init(a,b) memset(a,b,sizeof a)
bool vis[5002];
int main(){
int n,k;
int T;
scanf("%d",&T);
while(T--){
scanf("%d",&n);
init(vis,false);
rep(i,1,n)
scanf("%d%d",&num[i].l,&num[i].w);
sort(num+1,num+1+n);
int f=0;
int cont=0;
rep(i,1,n)
rep(j,i+1,n)
{
if(!vis[j]&&num[i].l<=num[j].l&&num[i].w<=num[j].w)
vis[j]=true;
}
int ans=0;
rep(i,1,n)
if(!vis[i]) ans++;
printf("%d\n",ans);
}
return 0;
}
开始肯定是需要排序的,然后我错误的思路就是将每一组数据依次和后面的数据对比,满足条件就标记为1,但是这种思路过上面另一组数据就错了,没有考虑到这种情况,这道题贪心解决的时候是需要记录当前点的
下面是参考大牛的思路写出的https://www.cnblogs.com/fstang/archive/2013/03/31/2991255.html
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
struct node{
int l,w;
bool operator < (const node &a)const{
if(a.l==l)
return a.w>w;
return a.l>l;
}
}num[5002],dp[5002];
const int INF=0x3f3f3f3f;
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define init(a,b) memset(a,b,sizeof a)
bool vis[5002];
int main(){
int n,k;
int T;
scanf("%d",&T);
while(T--){
scanf("%d",&n);
init(vis,false);
rep(i,1,n)
scanf("%d%d",&num[i].l,&num[i].w);
sort(num+1,num+1+n);
int f=0;
int cont=0;
rep(i,1,n){
f=0;
rep(j,1,cont)
{
if(num[i].l>=dp[j].l&&num[i].w>=dp[j].w)
{dp[j]=num[i];f=1;break;}
}
if(!f) dp[++cont]=num[i];
}
printf("%d\n",cont);
}
return 0;
}
下面是TLE的3636,如果将下面的方法改为上面1065的就能AC了
//这一题和poj1065的唯一的一处差别就是poj1065要求l'>=l&&w'>=w;
//但在poj3636这一道题目中就是把等号给去掉了,那就需要改动一下排序了,先说下改动的地方
//就是先排l,从小到大排列,然后再排w从大到小排列,为什么?先上一组数据 4 1 2 1 3 2 4 3 3
//如果是按照1065的方法排列的话,最后的排序就是上面的一组数据,模拟一下发现最后的答案是3,多了一个
//由于这样排列使得 1 2这个数据被2 4覆盖了,本来3 3是可以接到1 2的后面,但是只能另开一个空间,因此
//答案就多了一个。w从大到小排列就不会出现覆盖的情况了,这一点很难想到,坑。。。。。。。。。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
struct node{
int l,w;
bool operator < (const node &a)const{
if(a.l==l)
return a.w<w;
return a.l>l;
}
}num[20010],dp[20010];
const int INF=0x3f3f3f3f;
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define init(a,b) memset(a,b,sizeof a)
bool vis[20020];
int main(){
int n,k;
int T;
scanf("%d",&T);
while(T--){
scanf("%d",&n);
rep(i,1,n)
scanf("%d%d",&num[i].l,&num[i].w);
init(vis,false);
sort(num+1,num+1+n);
int f=0;
int cont=0;
rep(i,1,n){
if(!vis[i]){
int minl=num[i].l;
int minw=num[i].w;
rep(j,1+i,n)
{
if(!vis[j]&&num[j].l>minl&&num[j].w>minw)
{
minl=num[j].l;minw=num[j].w;vis[j]=1;
}
}
}
}
rep(i,1,n)
if(!vis[i]) cont++;
printf("%d\n",cont);
}
return 0;
}
再来一种通过二分的思路解决的
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
struct node{
int l,w;
bool operator < (const node &a)const{
if(a.l==l)
return a.w<w;
return a.l>l;
}
}num[20010],dp[20010];
const int INF=0x3f3f3f3f;
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define init(a,b) memset(a,b,sizeof a)
bool vis[20020];
int reasech(node a,int len)
{
int r=len;
int l=1;
while(l<=r)
{
int mid=(l+r)>>1;//dp数组是从大到小的排列顺序
if(dp[mid].w<a.w) r=mid-1;
else l=mid+1;
}
return l;
}
int main(){
int n,k;
int T;
scanf("%d",&T);
while(T--){
scanf("%d",&n);
rep(i,1,n)
scanf("%d%d",&num[i].l,&num[i].w);
sort(num+1,num+1+n);
int cont=0;
rep(i,1,n){
int temp=reasech(num[i],cont);
if(cont+1==temp) dp[++cont]=num[i];
else dp[temp]=num[i];
}
printf("%d\n",cont);
}
return 0;
}