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 特殊堆栈
vector的insert 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 ;
}