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

UVALive 4945 Free Goodies

2013-08-07 23:21 351 查看
题目大意:n个糖果,两个人PetraheJan,每个糖果对于这两个人都有一定的val值,Petra每次选对于自己val值最大的那个,如果一样,就选Jan的val值小的,Jan想让自己选的糖果的val值之和最大,如果有多种路径,那么就选使Petra最后的val最大的那种(真是好基友,好丽友。。 = =),告诉你先手,轮着来。问你最后他们两个的分别得val值之和。

思路:(1)DP做法:设d[ i ][ j ] 为Jan在前i个糖果中选j个能获得的最大值(Jan为先手),而相同情况Petra的分数最大,状态转移方程为:d[ i ][ j ] = max((d[ i -1 ][ j ].p + good[ i ].p,d[ i - 1][ j ].j ),(d[ i - 1][ j ].p ,d[ i - 1][ j ].j + good[ i ].p)),这里要注意 j 的边界,只能到一半。

我自己是没想到。。 看了别人的博客后才知道的。。 感觉对这种博弈问题不是很懂,先慢慢积累着吧。。

代码如下:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

const int INF = 0x0fffffff ;

const int MAXN = 1111 ;

char name[11] ;

struct Good
{
int p,j;
bool operator < (const Good &tmp) const
{
if(p==tmp.p) return j<tmp.j;
else return p>tmp.p;
}
} good[MAXN];

struct Node
{
int p,j;
Node(){}
Node(int a,int b) : p(a),j(b) {}
bool operator < (const Node &tmp) const
{
if(j == tmp.j) return p<tmp.p;
else return j<tmp.j;
}
}d[MAXN][MAXN],ans;

int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n;
scanf("%d",&n);
scanf("%s",name);
for(int i = 1;i<=n;i++)
scanf("%d%d",&good[i].p,&good[i].j);
sort(good+1,good+1+n);
for(int i = 0;i<=n;i++)
d[0][i].p = d[0][i].j = -INF;
if(name[0]=='P')
{
d[0][0].p = good[1].p;
d[0][0].j = 0;
for(int i = 1;i<n;i++)
good[i] = good[i+1];
n--;
}
else d[0][0].p = d[0][0].j = 0;
ans = d[0][0];
for(int i = 1;i<=n;i++)
{
for(int j = 0;j<=(i+1)/2;j++)
{
d[i][j] =d[i-1][j];
if(j>=1)
d[i][j] = max(d[i][j],Node(d[i-1][j-1].p,d[i-1][j-1].j+good[i].j));
d[i][j] = max(d[i][j],Node(d[i-1][j].p+good[i].p,d[i-1][j].j));
if(j==(n+1)/2)
ans = max(ans,d[i][j]);
//printf("d[%d][%d] p = %d,j = %d\n",i,j,d[i][j].p,d[i][j].j);
}
for(int j = (i+1)/2+1;j<=n;j++)
d[i][j].p = d[i][j].j = -INF;
}
printf("%d %d\n",ans.p,ans.j);
}
return 0;
}


(2)贪心。先按照Petra的顺序两人逐个选取,就会得到两组,一组是Petra的,一组是Jan的,然后再倒着来,对于每个Jan选取的糖果,对于当前点再往下找,去和本来Petra的糖果进行贪心,再交换,因为Jan可以随意取,他总可以拿到这些糖果。

其实我也是一知半解的,思维弱啊。。 如果大家谁能很清楚地解释其中的思想,欢迎和我交流。。

代码如下:

#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;

#define MP make_pair

typedef long long lld;

const int INF = 0x0fffffff ;

const int MAXN = 1111 ;

struct Good
{
int p,j;
Good(){}
Good(int a,int b) : p(a),j(b) {}
bool operator < (const Good& tmp) const
{
if(p == tmp.p) return j < tmp.j;
else return p > tmp.p;
}
} good[MAXN];

char name[11];

int vis[MAXN];

int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n;
scanf("%d",&n);
scanf("%s",name);
int a,b;
for(int i = 1;i<=n;i++)
{
scanf("%d%d",&a,&b);
good[i] = Good(a,b);
}
sort(good+1,good+1+n);
int flag ;
if(name[0]=='P')
flag =0 ;
else flag = 1;
for(int i = 1;i<=n;i++)
{
if(flag==1)
{
vis[i] = 1;
}
else vis[i]=0;
flag ^= 1;
}
for(int i = n;i>=1;i--)
{
if(vis[i])
{
vis[i] = 0;
int tmp = i;
for(int j = i+1;j<=n;j++)
if(!vis[j]&&good[j].j>=good[tmp].j)
tmp = j;
vis[tmp] = 1;
}
}
int val_p = 0,val_j = 0 ;
for(int i = 1;i<=n;i++)
{
if(vis[i])
val_j += good[i].j;
else val_p += good[i].p;
}
printf("%d %d\n",val_p,val_j);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: