• CSUST 2010-拼三角形(状压DP)


    题目链接:http://acm.csust.edu.cn/problem/2010
    CSDN食用链接:https://blog.csdn.net/qq_43906000/article/details/107675351
    Description

    Cwolf9有n根木棍,他现在想将他们拼成一些三角形,问最多能拼成多少三角形,每根木棍只能用一次。

    Input
    多组输入

    每组数据第一行一个数(n), ((1 leq n leq 18))。表示有n根木棍。

    接下来一行,(n)个数记为(a_i) 。表示第(i)根木棍的长度为(1leq a_ileq 100)

    Output
    对于每组数据每行输出一个数,表示用这nn根木棍可以拼出多少三角形。

    Sample Input 1
    6
    2 2 3 4 5 6
    6
    2 3 8 2 3 9
    5
    2 3 3 4 5

    Sample Output 1
    2
    2
    1

    emmm,这题可以直接暴搜DFS,但写起来很麻烦,std写的就是DFS,不过当时比赛的时候基本都是状压过的。。。。基本都是2500ms+,不过有个神仙只跑了18ms。。。。

    这题能用状压?我比较菜,我也是一脸蒙逼的,只不过在yd巨巨的一番教导之下终于过了。。。2980ms+???真nm刺激

    我们可以先枚举三根棍子合法想情况,并将其状态保存下来:

    sort(a+1,a+1+n);
    cnt=0;
    for (int i=1; i<=n; i++)
    	for (int j=i+1; j<=n; j++)
    		for (int k=j+1; k<=n; k++) {
    			if (a[i]+a[j]<=a[k]) continue;
    			sta[++cnt]=(1<<(i-1))|(1<<(j-1))|(1<<(k-1));
    		}
    

    接下来我们直接枚举这些合法的情况,然后继续枚举拿棍子的状态,这种状态有(1<<n)-1种,我们是对是否拿当前的合法状态进行DP,对于枚举的拿棍状态,如果合法的三根棍子都没有被用掉,那么就可以将这个状态转移过来:

    for (register int i=1; i<=cnt; i++) {
    	for (register int j=0; j<(1<<n); j++) {
    		if ((j&sta[i])==0) {//这三根棍子都没被用的时候
    			dp[j|sta[i]]=max(dp[j|sta[i]],dp[j]+1);
    			ans=max(dp[j|sta[i]],ans);
    		}
    	}
    }
    

    以下是AC代码:

    #include <bits/stdc++.h>
    using namespace std;
    
    int a[20];
    int sta[1<<19],cnt=0,dp[1<<19];
    
    int digt(int x)
    {
    	int ans=0;
    	while(x){
    		if (x&1) ans++;
    		x>>=1;
    	}
    	return ans;
    }
    
    int main(int argc, char const *argv[])
    {
    	int n;
    	while (~scanf ("%d",&n)){
    		memset(dp,0,sizeof dp);
    		for (int i=1; i<=n; i++)
    			scanf ("%d",&a[i]);
    		sort(a+1,a+1+n);
    		cnt=0;
    		for (int i=1; i<=n; i++)
    			for (int j=i+1; j<=n; j++)
    				for (int k=j+1; k<=n; k++){
    					if (a[i]+a[j]<=a[k]) continue;
    					sta[++cnt]=(1<<(i-1))|(1<<(j-1))|(1<<(k-1));
    				}
    		int ans=0;
    		for (register int i=1; i<=cnt; i++){
    			for (register int j=0; j<(1<<n); j++){
    				if ((j&sta[i])==0) {//这三根棍子都没被用的时候
    					dp[j|sta[i]]=max(dp[j|sta[i]],dp[j]+1);
    					ans=max(dp[j|sta[i]],ans);
    				}
    			}
    		}
    		printf("%d
    ",ans);
    	}
    	return 0;
    }
    
    路漫漫兮
  • 相关阅读:
    【ES6】函数的扩展
    NSFileManger使用介绍
    委托,曾将让我头疼难以理解
    【HDOJ】1914 The Stable Marriage Problem
    MySQL修改配置优化插入性能
    MySQL配置文件的编码问题
    MyBatis批量更新时提示"You have an error in your SQL syntax"
    MyBatis批量更新返回受影响数
    log4j.properties配置说明
    删除Win10的OneDrive
  • 原文地址:https://www.cnblogs.com/lonely-wind-/p/13399822.html
Copyright © 2020-2023  润新知