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 的边界,只能到一半。
我自己是没想到。。 看了别人的博客后才知道的。。 感觉对这种博弈问题不是很懂,先慢慢积累着吧。。
代码如下:
(2)贪心。先按照Petra的顺序两人逐个选取,就会得到两组,一组是Petra的,一组是Jan的,然后再倒着来,对于每个Jan选取的糖果,对于当前点再往下找,去和本来Petra的糖果进行贪心,再交换,因为Jan可以随意取,他总可以拿到这些糖果。
其实我也是一知半解的,思维弱啊。。 如果大家谁能很清楚地解释其中的思想,欢迎和我交流。。
代码如下:
思路:(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; }
相关文章推荐
- UVALive 4945 Free Goodies
- uvalive4945(dp,贪心)
- UVALive 6680 Join the Conversation (模拟)
- UVALive 6047 Perfect Matching(字符串哈希)#by zh
- UVAlive 7041 The Problem to Slow Down You(回文树)
- UVALive 3363 String Compression (区间DP,4级)
- UVALive - 6320 Encrypted Password
- UVALive 3668 A Funny Stone Game
- UVALive - 5854 最短路
- UVALive 2238 Fixed Partition Memory Management(二分完美匹配)
- UVALive6662 The Last Ant
- UVALive - 3971 Assemble
- UVALive 6658 - Fiasco(BFS)
- UVALive 4614 Moving to Nuremberg
- UVALive - 3942 Remember the Word[Trie DP]
- UVALive 6084 Happy Camper(数学题)
- UvaLive-3713-Astronauts
- UVAlive 3490 AC自动机+(整数)高斯消元
- UVALive6859 Points +凸包
- UVALive - 5713 最小生成树