您的位置:首页 > 编程语言 > Go语言

HDU 4341 Gold miner (分组背包)

2015-08-20 18:33 405 查看
先把线按照距离原点的距离排序,然后用叉积把在同一条直线上的点放在一起,

把在同一条线上的点中的前i个点当成一个点就转化成了分组背包。

写if(kas++) putchar('\n') 居然PE了,PE选手

#include<bits/stdc++.h>
using namespace std;
int N,T;
const int maxn = 203;
const int MAXT = 40005;
struct Point
{
int x,y,t,v;

}P[maxn];

bool vis[maxn];
vector<int> Line[maxn];
int Line_cnt;
#define PB push_back

int Dot(const Point &a,const Point& b) { return a.x*b.x+a.y*b.y; }
double Length(const Point &x) { return sqrt(Dot(x,x)); }
int Cross(Point &a,Point &b)
{
return a.x*b.y-b.x*a.y;
}
bool operator < (const Point& a,const Point & b) { return Length(a)<Length(b); }

void init()
{
memset(vis,0,sizeof(vis));
for(int i = 0; i < N; i++){
scanf("%d%d%d%d",&P[i].x,&P[i].y,&P[i].t,&P[i].v);
}
sort(P,P+N);
Line_cnt = 0;
for(int i = 0; i < N; i++)if(!vis[i]){
Line[Line_cnt].clear();
for(int j = i; j < N; j++)if(!vis[j]){
if(Cross(P[i],P[j]) == 0){
vis[j] = true;
Line[Line_cnt].PB(j);
}
}
Line_cnt++;
}
}

int f[2][MAXT];

void dp()
{
fill(f[0],f[0]+1+T,0);
fill(f[1],f[1]+1+T,0);
for(int i = 0; i < Line_cnt; i++){
int pre = i&1,cur = pre^1;
int totV = 0, totT = 0;
for(int j = 0; j < Line[i].size(); j++){
Point& x = P[Line[i][j]];
totV += x.v; totT += x.t;
for(int k = T; k >= totT; k--){
f[cur][k] = max(f[cur][k],f[pre][k-totT]+totV);
}
}
for(int k = 0; k <= T; k++){
f[cur][k] = max(f[cur][k],f[pre][k]);
}
}
}

int main()
{
int kas = 0;
while(~scanf("%d%d",&N,&T)){
init();
dp();
printf("Case %d: %d\n",++kas,max(f[0][T],f[1][T]));
}
return 0;
}


当时并不知道如何用一维数组实现,补上一维的伪代码

for 所有的组k

for v=V..0 //从大到小枚举V

for 所有的i属于组k

f[v]=max{f[v],f[v-c[i]]+w[i]}//从小的V转移,是上一组的状态
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: