NYOJ 832 合并游戏

合并游戏

时间限制:1000 ms  |  内存限制:65535 KB

难度:4

描述
大家都知道Yougth除了热爱编程之外,他还有一个爱好就是喜欢玩。某天在河边玩耍的时候,他发现了一种神奇的石子,当把两个石子放在一起的时候,后一个石子会消失,而且会蹦出一定数量的金币,这可乐坏了Yougth,但是他想得到最多的金币,他该怎么做?
输入
首先一行,一个n(1<=n<=10),表示有n个石子。接下来n*n的一个矩阵,Aij表示第i个和第j个合并蹦出的金币值(小于10000,注意合并后j会消失)。
输出
输出最多能得到的金币值。
样例输入
2
0 4
1 0
3
0 20 1
12 0 1
1 10 0
样例输出
4
22
来源
Yougth原创
上传者
TC_杨闯亮

解题:在wdd的指导,终于搞定了!wdd,神dp啊!状压dp。。。

二进制1111表示还剩4个没有选,二进制1101表示还剩三个没选,1101可以由1111与另外三个合并转移而来。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cmath>
 5 #include <algorithm>
 6 #include <climits>
 7 #include <vector>
 8 #include <queue>
 9 #include <cstdlib>
10 #include <string>
11 #include <set>
12 #include <stack>
13 #define LL long long
14 #define pii pair<int,int>
15 #define INF 0x3f3f3f3f
16 using namespace std;
17 int mp[12][12],n;
18 vector<int>g[100];
19 bool vis[20480];
20 int dp[100000];
21 void init() {
22     int i,j,k,temp,v,u;
23     memset(vis,false,sizeof(vis));
24     for(i = 0; i < 100; i++) g[i].clear();
25     g[0].push_back((1<<n)-1);
26     g[n].push_back(0);
27     vis[0] = true;
28     vis[(1<<n)-1] = true;
29     for(i = 1; i <= n; i++) {
30         for(j = 0; j < g[i-1].size(); j++) {
31             temp = g[i-1][j];
32             for(k = 0; k < n; k++) {
33                 u = temp&(1<<k);
34                 if(u) {
35                     v = temp^(1<<k);
36                     if(vis[v]) continue;
37                     vis[v] = true;
38                     g[i].push_back(v);
39                 }
40             }
41         }
42     }
43 }
44 int go(int x){
45     char s[20];
46     int pos[120],m = 0,i,j,y,theMax = 0;
47     for(i = 0; i < n; i++)
48         if(x&(1<<i)) pos[m++] = i;
49     for(i = 0; i < n; i++){
50         if((x&(1<<i)) == 0){
51             y = x^(1<<i);
52             for(j = 0; j < m; j++){
53                 theMax = max(theMax,dp[y]+mp[pos[j]][i]);
54             }
55         }
56     }
57     return theMax;
58 }
59 int main() {
60     int i,j,ans;
61     while(~scanf("%d",&n)) {
62         init();
63         for(i = 0; i < n; i++) {
64             for(j = 0; j < n; j++)
65                 scanf("%d",mp[i]+j);
66         }
67         memset(dp,0,sizeof(dp));
68         for(i = 1; i <= n; i++){
69             for(j = 0; j < g[i].size(); j++){
70                 dp[g[i][j]] = go(g[i][j]);
71             }
72         }
73         for(ans = i = 0; i < g[n-1].size(); i++)
74             ans = max(ans,dp[g[n-1][i]]);
75         printf("%d\n",ans);
76     }
77     return 0;
78 }

NYOJ 832 合并游戏,布布扣,bubuko.com

时间: 2024-10-26 20:18:28

NYOJ 832 合并游戏的相关文章

NYOJ 905 卡片游戏

卡片游戏 时间限制:1000 ms  |  内存限制:65535 KB 难度:1 描述 小明最近宅在家里无聊,于是他发明了一种有趣的游戏,游戏道具是N张叠在一起的卡片,每张卡片上都有一个数字,数字的范围是0~9,游戏规则如下: 首先取最上方的卡片放到桌子上,然后每次取最上方的卡片,放到桌子上已有卡片序列的最右边或者最左边.当N张卡片全部都放到桌子上后,桌子上的N张卡片构成了一个数.这个数不能有前导0,也就是说最左边的卡片上的数字不能是0.游戏的目标是使这个数最小. 现在你的任务是帮小明写段程序,

NYOJ 614 纸牌游戏

纸牌游戏 时间限制:1000 ms  |  内存限制:65535 KB 难度:2 描述 设2n张牌分别标记为1,2,-,n,n+l,-,2n,初始时这2n张牌按其标号从小到大排列. 经一次洗牌后,原来的排列顺序变成n+l,l,n+2,2,··,,2n,n. 即前n张牌被放到偶数位置2,4,·,·,2n,而后n张牌被放到奇数位置1,3,-,2n-l. 可以证明对于任何一个自然数n,经过若干次洗牌后可恢复初始状态. 编程任务:对于给定的n的值(n<=24000),编程计算最少经过多少次洗牌可恢复到初

合并游戏

合并游戏 merge.cpp/c/pas (1s/256M)   题目描述 Cindy和Dan在玩一个游戏. 一开始Cindy想出了N个数,接着她把这N个数全部给了Dan. Dan得到这组数后,它会挑出3个数(如果不足3个则全部挑出).Dan会把这几个数加起来变成一个数,然后再把这个数与剩下的数再放到一起.Dan会一直这样做,直到最后只剩下一个数. Cindy则会在旁边记下每次Dan得到的数,她把这些数加起来,作为本次游戏的得分.她想知道,对于一组数,Dan能得到的最大的得分是多少? 输入格式

NYOJ 737 合并石子(一)

石子合并(一) 时间限制:1000 ms  |  内存限制:65535 KB 难度:3 描述     有N堆石子排成一排,每堆石子有一定的数量.现要将N堆石子并成为一堆.合并的过程只能每次将相邻的两堆石子堆成一堆,每次合并花费的代价为这两堆石子的和,经过N-1次合并后成为一堆.求出总的代价最小值. 输入 有多组测试数据,输入到文件结束. 每组测试数据第一行有一个整数n,表示有n堆石子. 接下来的一行有n(0< n <200)个数,分别表示这n堆石子的数目,用空格隔开 输出 输出总代价的最小值,

nyoj832 合并游戏(状态压缩DP)

题意 : n个石子, 给你一个n*n矩阵, A[i][j]表示第i个和第j个合并蹦出的金币值, 合并完石子 j 消失.求合并所有石子后,所得的最大金币数. 分析 :     1. 题中给的数据范围  n(1<=n<=10)  也就是说最多10个石子, 那么我们不妨用一个二进制串来表示合并的状态,1表示没被合并,0表示合并后消失了,例如    (1001)四个石子第2.3个被合并了.     2. 用d[x]来存储合并到x状态时,所得的最大金币数,例如 d[1001] 表示合并2 , 3 后所得

NYOJ 559 报数游戏

报数游戏 时间限制:1000 ms  |  内存限制:65535 KB 难度:2 描述     n 个人站成一行玩一个报数游戏.所有人从左到右编号为 1 到 n.游戏开始时,最左边的人报 1,他右边的人报 2,编号为 3 的人报 3,等等.当编号为 n 的人(即最右边的人)报完 n 之后,轮到他左边的人(即编号为n-1 的人)报 n+1,然后编号为 n-2 的人报 n+2,以此类推.当最左边的人再次报数之后,报数方向又变成从左到右,依次类推. 为了防止游戏太无聊,报数时有一个特例:如果应该报的数

NYOJ 562 盒子游戏

盒子游戏 时间限制:1000 ms  |  内存限制:65535 KB 难度:3 描述     有两个相同的盒子,其中一个装了 n 个球,另一个装了一个球.Alice 和 Bob 发明了一个游戏,规则如下:Alice 和 Bob 轮流操作,Alice 先操作.每次操作时,游戏者先看看哪个盒子里的球的数目比较少,然后清空这个盒子(盒子里的球直接扔掉),然后把另一个盒子里的球拿一些到这个盒子中,使得两个盒子都至少有一个球.如果一个游戏者无法进行操作,他(她)就输了.下图是一个典型的游戏: 面对两个各

ACM--模拟--nyoj 559--报数游戏--湖南第七届省赛

南阳oj题目地址:传送门 报数游戏 时间限制:1000 ms  |  内存限制:65535 KB 难度:2 描述     n 个人站成一行玩一个报数游戏.所有人从左到右编号为 1 到 n.游戏开始时,最左边的人报 1,他右边的人报 2,编号为 3 的人报 3,等等.当编号为 n 的人(即最右边的人)报完 n 之后,轮到他左边的人(即编号为n-1 的人)报 n+1,然后编号为 n-2 的人报 n+2,以此类推.当最左边的人再次报数之后,报数方向又变成从左到右,依次类推. 为了防止游戏太无聊,报数时

NYOJ832 合并游戏(简单状压DP)

AC代码: #include<stdio.h> #include<string.h> #define max(a,b) (((a)>(b))?(a):(b)) int dp[10000],a[12][12],n; int dj(int x){ int i,j,temp,Mx=0,mx; if(dp[x]!=-1) return dp[x]; //搜过的状态要标记, 这要注意!! 不写的话会超时 if(x==0) return 0; for(i=0;i<n;i++){ m