HDU 4341 Gold miner 分组背包
第一篇题解- -。
传送门:http://acm.hdu.edu.cn/showproblem.php?pid=4341
题意:给出黄金矿工的地图上各个金块的坐标,得到它的时间,价值,
在一条线上的只能先抓第一个才能抓第二个,求限定时间内,最多能获得
多少钱。
初始点是(0,0)
把在一条直线的分为一个组,然后组的成员就是 第一个,第一个+第二个.....;
每组取一个或者不取,这样就是分组背包问题;
注意对金块按y排序,这样就能保证第一个在第二个前...;
确认在一条线上用 x/y 值来存WA了,要用交叉相乘且相等确认。
————————————————————————————————————
渣渣之见,随便转载。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define maxn 205 5 #define maxx 40010 6 using namespace std; 7 8 int dp[maxx],tm[maxn],gr[maxn]; 9 10 typedef struct{ 11 int x,y; 12 int t,v; 13 }hehe; 14 15 bool cmp(hehe a,hehe b) 16 { 17 return a.y<b.y; // 对y进行排序 18 } 19 20 typedef struct{ 21 int t,v; 22 }he; 23 24 he b[maxn][maxn]; 25 hehe a[maxn]; 26 27 int is_oneline(int i,int j) // 一开始在结构体中用 x/y 存了比较WA了 28 { // 所以这里用向量乘积交叉相乘且相等 29 if(a[i].x*a[j].y==a[i].y*a[j].x) 30 return 1; 31 return 0; 32 } 33 34 int main() 35 { 36 // freopen("C:\\Users\\ZDH\\Desktop\\a.txt","r",stdin); 37 int n,T,ca=1; 38 while(~scanf("%d %d",&n,&T)) 39 { 40 memset(dp,0,sizeof dp); 41 memset(tm,0,sizeof tm); 42 memset(gr,0,sizeof gr); 43 44 int gro=0; 45 for(int i=0;i<n;i++) 46 scanf("%d %d %d %d",&a[i].x, 47 &a[i].y,&a[i].t,&a[i].v); 48 sort(a,a+n,cmp); 49 50 for(int i=0;i<n;i++) 51 if(tm[i]==0) 52 { 53 tm[i]=1; 54 b[gro][gr[gro]].t=a[i].t; 55 b[gro][gr[gro]].v=a[i].v; 56 gr[gro]++; 57 for(int j=0;j<n;j++) 58 if(tm[j]==0 && is_oneline(i,j) ) 59 { 60 tm[j]=1; 61 b[gro][gr[gro]].t=b[gro][gr[gro]-1].t+a[j].t; 62 b[gro][gr[gro]].v=b[gro][gr[gro]-1].v+a[j].v; 63 gr[gro]++; 64 } 65 gro++; 66 } 67 68 for(int i=0;i<gro;i++) 69 for(int t=T;t>=0;t--) 70 for(int j=0;j<gr[i];j++) 71 if(t>=b[i][j].t) // 分组背包的DP dp[v]=max(dp[v],dp[v-vi[i]]+w[i]); 72 dp[t]=max(dp[t],dp[t-b[i][j].t]+b[i][j].v); 73 74 printf("Case %d: %d\n",ca++,dp[T]); 75 } 76 }