poj 3674 枚举+贪心与搜索
2012-12-05 19:34
232 查看
http://acm.pku.edu.cn/JudgeOnline/problem?id=3674
看了别人的代码,好久才领悟到什么意思,于是就写了个 枚举+贪心 但耗时比较多,1400多ms。主要是应在每种级别中选取攻击力前六的,这样得到的规模最大为66.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
vector<int> v[11];
int num[11],b[11],c[7],m;
double res;
struct Node
{
int index,e;
}node[7];
int cmp(int x,int y)
{
return x>y;
}
int cmpp(Node x,Node y)
{
return x.e>y.e;
}
void dfs(int dep)
{
int i;
if(dep==m)
{
node[0].index=0;
node[0].e=-1;
for(i=1;i<m;i++)
{
node[i].index=i;
node[i].e=c[i-1];
}
sort(node,node+m,cmpp);
int dns[11]={0};
int d[7];
for(i=0;i<m;i++)
{
int p=node[i].index;
d[p]=v[c[p]][dns[c[p]]++];
}
double sum=d[0];
for(i=1;i<m;i++)
sum+=d[i]*(1.0+c[i-1]*1.0/10);
if(sum>res)
res=sum;
return;
}
for(i=0;i<11;i++)
{
if(b[i]<num[i])
{
b[i]++;
c[dep]=i;
dfs(dep+1);
b[i]--;
}
}
}
int main()
{
int n,i,d,e;
while(scanf("%d",&n)!=EOF)
{
for(i=0;i<11;i++)
v[i].clear();
m=n>=6?6:n;
while(n--)
{
scanf("%d%d",&d,&e);
v[e].push_back(d);
}
for(i=0;i<11;i++){
sort(v[i].begin(),v[i].end(),cmp);
num[i]=v[i].size();
}
res=0;
memset(b,0,sizeof(b));
dfs(0);
printf("%.0lf\n",res);
}
return 0;
}
看了超哥的提示,突然发现此规模搜索确实比较好,稍微加点剪枝
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
vector<int> v[11];
int num[11],c[7],m,l;
bool visit[70];
double res;
struct Node
{
int s,e;
}node[67];
int cmp(int x,int y)
{
return x>y;
}
int cmpp(Node x,Node y)
{
if(x.e==y.e)
return x.s>y.s;
return x.e>y.e;
}
void dfs(int i,double value,int s)
{
if(i==m)
{
if(value>res)
res=value;
return;
}
if(value+(m-i)*node[0].e*2<=res)
return;
int j;
for(j=0;j<l;j++)
{
if(!visit[j])
{
visit[j]=1;
dfs(i+1,value+(1.0+s*1.0/10)*node[j].e,node[j].s);
visit[j]=0;
}
}
}
int main()
{
int n,i,j,d,e;
while(scanf("%d",&n)!=EOF)
{
for(i=0;i<11;i++)
v[i].clear();
m=n>=6?6:n;
while(n--)
{
scanf("%d%d",&d,&e);
v[e].push_back(d);
}
for(i=0;i<11;i++){
sort(v[i].begin(),v[i].end(),cmp);
}
l=0;
for(i=0;i<11;i++)
{
for(j=0;j<v[i].size()&&j<6;j++)
{
node[l].e=v[i][j];
node[l++].s=i;
}
}
sort(node,node+l,cmpp);
res=0;
memset(visit,0,sizeof(visit));
dfs(0,0,0);
printf("%.0lf\n",res);
}
return 0;
}
看了别人的代码,好久才领悟到什么意思,于是就写了个 枚举+贪心 但耗时比较多,1400多ms。主要是应在每种级别中选取攻击力前六的,这样得到的规模最大为66.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
vector<int> v[11];
int num[11],b[11],c[7],m;
double res;
struct Node
{
int index,e;
}node[7];
int cmp(int x,int y)
{
return x>y;
}
int cmpp(Node x,Node y)
{
return x.e>y.e;
}
void dfs(int dep)
{
int i;
if(dep==m)
{
node[0].index=0;
node[0].e=-1;
for(i=1;i<m;i++)
{
node[i].index=i;
node[i].e=c[i-1];
}
sort(node,node+m,cmpp);
int dns[11]={0};
int d[7];
for(i=0;i<m;i++)
{
int p=node[i].index;
d[p]=v[c[p]][dns[c[p]]++];
}
double sum=d[0];
for(i=1;i<m;i++)
sum+=d[i]*(1.0+c[i-1]*1.0/10);
if(sum>res)
res=sum;
return;
}
for(i=0;i<11;i++)
{
if(b[i]<num[i])
{
b[i]++;
c[dep]=i;
dfs(dep+1);
b[i]--;
}
}
}
int main()
{
int n,i,d,e;
while(scanf("%d",&n)!=EOF)
{
for(i=0;i<11;i++)
v[i].clear();
m=n>=6?6:n;
while(n--)
{
scanf("%d%d",&d,&e);
v[e].push_back(d);
}
for(i=0;i<11;i++){
sort(v[i].begin(),v[i].end(),cmp);
num[i]=v[i].size();
}
res=0;
memset(b,0,sizeof(b));
dfs(0);
printf("%.0lf\n",res);
}
return 0;
}
看了超哥的提示,突然发现此规模搜索确实比较好,稍微加点剪枝
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
vector<int> v[11];
int num[11],c[7],m,l;
bool visit[70];
double res;
struct Node
{
int s,e;
}node[67];
int cmp(int x,int y)
{
return x>y;
}
int cmpp(Node x,Node y)
{
if(x.e==y.e)
return x.s>y.s;
return x.e>y.e;
}
void dfs(int i,double value,int s)
{
if(i==m)
{
if(value>res)
res=value;
return;
}
if(value+(m-i)*node[0].e*2<=res)
return;
int j;
for(j=0;j<l;j++)
{
if(!visit[j])
{
visit[j]=1;
dfs(i+1,value+(1.0+s*1.0/10)*node[j].e,node[j].s);
visit[j]=0;
}
}
}
int main()
{
int n,i,j,d,e;
while(scanf("%d",&n)!=EOF)
{
for(i=0;i<11;i++)
v[i].clear();
m=n>=6?6:n;
while(n--)
{
scanf("%d%d",&d,&e);
v[e].push_back(d);
}
for(i=0;i<11;i++){
sort(v[i].begin(),v[i].end(),cmp);
}
l=0;
for(i=0;i<11;i++)
{
for(j=0;j<v[i].size()&&j<6;j++)
{
node[l].e=v[i][j];
node[l++].s=i;
}
}
sort(node,node+l,cmpp);
res=0;
memset(visit,0,sizeof(visit));
dfs(0,0,0);
printf("%.0lf\n",res);
}
return 0;
}
相关文章推荐
- 枚举搜索+贪心:POJ2718--Smallest Difference(解一)
- 【搜索】POJ-2718 贪心+枚举
- POJ 1204 Word Puzzles // 字典树,枚举, 搜索
- poj -- 1042 Gone Fishing(枚举+贪心)
- POJ 1042 Gone fishing(枚举+贪心)
- POJ 1018 Communication System(搜索/贪心/动归)
- POJ 1042 Gone Fishing【枚举+贪心】
- poj 3977 折半枚举二分搜索
- POJ 1166 暴力搜索 即 枚举
- poj 1042 Gone Fishing dp或枚举贪心
- POJ 1042 Gone Fishing (枚举+贪心) [12#11#16 daily] #by Plato
- 寒假训练——POJ - 2488 A Knight's Journey 搜索+贪心
- POJ 1505:二分枚举+贪心
- poj 1018 Communication System 枚举 VS 贪心
- POJ 1042 钓鱼问题 贪心枚举及动态规划
- POJ 1042 Gone Fishing(贪心+枚举)
- poj 1042 钓鱼问题 枚举+贪心
- POJ-1042-Gone Fishing-枚举+贪心
- POJ 1753 Flip Game 暴力搜索(dfs加枚举)
- POJ 3977 折半枚举+二分搜索