4743. 【NOIP2016提高A组模拟9.2】积木

64 篇文章 0 订阅
19 篇文章 0 订阅

Description

Input

Output

Sample Input

3
8 7 6
3 9 4
1 10 5

Sample Output

18

Data Constraint

Solution

10 分做法 输出 max{a, b, c}。

40 分做法 :成全排列,然后枚举每个积⽊哪个⾯朝上,时间复杂度 O(n! · 3 n )。

100 分做法 显然是状态压缩 DP。设计状态 f[S][i][0/1/2] 表示已经了集合S内的积,最顶上是编号为i的积,它的哪个朝上。转移时枚举不在S内的积,以及朝上的判断即可。时间复杂度O(2n·(3n)2)。 

以上就是题解给出的方法,但是考试的时候我打了一个dfs不知为何就过了,这数据也太水了吧......

 

Code1

#include<cstdio>
#include<algorithm>
using namespace std;
int n;
struct node{
	int a,b,c;
} c[20];
int full;
int ans,dp[(1<<15)+10][20][3];
int main()
{
    scanf("%d",&n);
    full=(1<<n)-1;
    for(register int i=1;i<=n;++i){
	scanf("%d%d%d",&c[i].a,&c[i].b,&c[i].c);
	dp[1<<i-1][i][0]=c[i].c;
	ans=max(ans,c[i].c);
	dp[1<<i-1][i][1]=c[i].b;
	ans=max(ans,c[i].b);
	dp[1<<i-1][i][2]=c[i].a;
	ans=max(ans,c[i].a);
    }
    for(register int i=0;i<=full;++i)
        for(register int j=1;j<=n;++j)
            if(i&(1<<j-1))
                for(register int k=1;k<=n;++k)
                    if(!(i&(1<<k-1))){
                        for(register int f=0;f<3;++f)
                            for(register int ff=0;ff<3;++ff){
                                int cur[3],pre[3];
                                if(ff==0) cur[0]=c[k].a,cur[1]=c[k].b,cur[2]=c[k].c;
                                else if(ff==1) cur[0]=c[k].a,cur[1]=c[k].c,cur[2]=c[k].b;
                                else cur[0]=c[k].b,cur[1]=c[k].c,cur[2]=c[k].a;
                                if(f==0) pre[0]=c[j].a,pre[1]=c[j].b,pre[2]=c[j].c;
                                else if(f==1) pre[0]=c[j].a,pre[1]=c[j].c,pre[2]=c[j].b;
                                else pre[0]=c[j].b,pre[1]=c[j].c,pre[2]=c[j].a;
                                if((cur[0]<=pre[0]&&cur[1]<=pre[1])||(cur[0]<=pre[1]&&cur[1]<=pre[0])) dp[i|(1<<k-1)][k][ff]=max(dp[i|(1<<k-1)][k][ff],dp[i][j][f]+cur[2]),ans=max(ans,dp[i|(1<<k-1)][k][ff]);
                            }
                    }
    printf("%d\n",ans);
}

 Code2

 

#include<cstdio>
#include<algorithm>
#define N 16
using namespace std;
int ans,i,n,a[N][4],f[N][N][3];
bool bz[N];
void dg(int x,int c,int k,int s)
{
    ans=max(ans,s);
    if (x>n) return;
    for (int i=1;i<=n;i++){
	if (bz[i]==1) continue;
	bz[i]=1;
	if (a[i][1]<=c&&a[i][3]<=k||a[i][1]<=k&&a[i][3]<=c)dg(x+1,a[i][1],a[i][3],s+a[i][2]);
	if (a[i][1]<=c&&a[i][2]<=k||a[i][1]<=k&&a[i][2]<=c)dg(x+1,a[i][1],a[i][2],s+a[i][3]);
	if (a[i][2]<=c&&a[i][3]<=k||a[i][2]<=k&&a[i][3]<=c)dg(x+1,a[i][2],a[i][3],s+a[i][1]);
	bz[i]=0;
    }
}
int main()
{
    scanf("%d",&n);
    for (i=1;i<=n;i++){
        scanf("%d%d%d",&a[i][1],&a[i][2],&a[i][3]);
    }
    dg(1,2147483647,2147483647,0);
    printf("%d",ans);
} 

 



作者:zsjzliziyang 
QQ:1634151125 
转载及修改请注明 
本文地址:https://blog.csdn.net/zsjzliziyang/article/details/82721748

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值