合并游戏
时间限制:
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
-
首先一行,一个n(1<=n<=10),表示有n个石子。
哎,也就只能做做这种水题了,忧伤
10个石头,其实比较容易想到当剩余固定石头时,这个最优解是固定的,那么就使用记忆化搜索,用一个数的每一个二进制位表示当前这个石头有没有,那么当前状态就由去掉当前剩余石头中任意一个石头后的状态的最优解加上这个消失的石头的金钱,注意每一个消失的石头可以由其他石头相碰取最大值
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
int val[11][11];
int dp[2000];
int n;
int dfs(int now){
if (now==0) return 0;
//bool is[11]={0};
if (dp[now]!=0) return dp[now];
int t=now;
int k=0;
vector<int> v;
while(now!=0){
if (now%2==1) v.push_back(k);
now/=2;
k++;
}
if (v.size()==1) return 0;
for (int i=0;i<v.size();i++){
for (int j=0;j<v.size();j++){
if (i!=j){
dp[t]=max(dp[t],dfs(t-(1<<v[i]))+val[v[j]][v[i]]);
}
}
}
return dp[t];
}
int main(){
while(cin>>n){
memset(dp,0,sizeof(dp));
for (int i=0;i<n;i++){
for (int j=0;j<n;j++){
cin>>val[i][j];
}
}
cout<<dfs( (1<<n)-1 )<<endl;
}
}