天梯赛-L3

L3-001 凑零钱 (30 分)
看上去是一个01背包 , 实际上就是个01背包。
当然也可以搜索去做 , 只要剪枝剪的好就能AC 。

对于这个题 , 物品的重量就是每一枚硬币的面值 , 价值同样也是每一枚硬币的面值 ,最大容量就是我们要凑的总面值。 显然 ,只要dp[m] == m , 那么我们就有可行方案 ,但是对于多个可行方案如何找到最小序列呢?

我们首先想到在更新答案的时候标记一下 ,最后把标记点输出一下 。但是这样我们并不能保证序列最小 。

我们想到把序列从大到小排序 , 这样能保证小的面值在更新答案的时候会覆盖大的面值 , 最后再输出标记的序列就能保证是最小序列了 。

Code:

#include <bits/stdc++.h>
using namespace std ;
const int N = 1e4 + 10 ;
int dp[N] , a[N] ;
bool vis[N][N/2] ;
bool cmp(const int &a , const int &b) {return a > b ;}
int main()
{
    int n , m ;
    scanf("%d%d" , &n , &m) ;
    for(int i = 1 ; i <= n ; i ++) scanf("%d" , &a[i]) ;
    sort(a + 1 , a + 1 + n , cmp) ;
    for(int i = 1 ; i <= n ; i ++)
        for(int j = m ; j >= a[i] ; j --)
        {
            if(dp[j] <= dp[j-a[i]] + a[i])
            {
                dp[j] = dp[j-a[i]] + a[i] ;
                vis[i][j] = true ;
            }
        }
    if(dp[m] == m)
    {
        int w = m , id = n ;
        while(w)
        {
            if(vis[id][w])
            {
                if(w != m) printf(" ") ;
                printf("%d" , a[id]) ;
                w -= a[id] ;
            }
            id -- ;
        }
    }
    else
    {
        printf("No Solution") ;
    }
    return 0 ;
}

L3-002 特殊堆栈
vectorinsert yydx!
注意一下是从指针前面插入。

#include <bits/stdc++.h>
using namespace std ;
vector<int> num ;
stack<int> q ;
int n ;
int main() {
	cin >> n ;
	vector<int>::iterator it ;
	while(n --) {
		string s ; cin >> s ;
		if(s == "Pop") {
			if(num.size() == 0) printf("Invalid\n") ;
			else printf("%d\n" , q.top()) , it = lower_bound(num.begin() , num.end() , q.top()) , num.erase(it) , q.pop() ;
		}
		else if(s == "Push") {
			int x ; 
			cin >> x ;
			it = lower_bound(num.begin() , num.end() , x) ;
			num.insert(it , x) ;
			q.push(x) ;
		}
		else {
			if(num.size() == 0) {
				printf("Invalid\n") ;
				continue ;
			}
			int t = (num.size() % 2 == 0) ? num.size() / 2 : (num.size() + 1) / 2 ;
			printf("%d\n" , num[t-1]) ;
		}
	}
}

L3-003 社交集群
set & lower_bound yydx !

#include <bits/stdc++.h>
using namespace std ;
int f[1001] , sz[1001] ;
int ans[1001] , tot ;
set<int> v[1001] ; 
int n ;
int find(int x) {
	if(x == f[x]) return x ;
	return f[x] = find(f[x]) ;
}
void merge(int x , int y) {
	int fx = find(x) ;
	int fy = find(y) ;
	if(fy != fx) f[fx] = fy , sz[fy] += sz[fx] ;
	
}
bool judge(int x , int y) {
	set<int>::iterator it1 , it2 ;
	for(it1 = v[x].begin() ; it1 != v[x].end() ; it1 ++) {
		it2 = v[y].lower_bound(*it1) ;
		if(it2 != v[y].end() && *it2 == *it1) return true ;
//		printf("%d " , *it2) ;
	}
	return false ;
}
int main() {
	scanf("%d" , &n) ;
	for(int i = 1 ; i <= n ; i ++) {
		f[i] = i ;
		sz[i] = 1 ;
		int k ;
		scanf("%d" , &k) ;
		getchar() ; getchar() ;
		for(int j = 1 ; j <= k ; j ++) {
			int x ;
			scanf("%d" , &x) ;
			v[i].insert(x) ;
		} 
	}
	for(int i = 1 ; i <= n ; i ++) {
		for(int j = i + 1 ; j <= n ; j ++) {
			if(judge(i , j)) merge(i , j) ;
		}
	}
	for(int i = 1 ; i <= n ; i ++) 
		if(f[i] == i) 
			ans[++tot] = sz[i] ;
	sort(ans + 1 , ans + 1 + tot) ;
//	printf("%d" , judge(4 , 2));
//	for(int i = 1 ; i <= n ; i ++) printf("%d " , find(i)) ;
	printf("%d\n" , tot) ;
	for(int i = tot ; i >= 1 ; i --) {
		printf("%d" , ans[i]) ;
		if(i != 1) printf(" ") ; 
	}
	return 0 ;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值