[Acwing|蓝桥] 1243. 糖果 状态压缩+01背包

前言

传送门 :

思路

因为数据范围很小, 我们考虑使用 d p dp dp

显然对于每袋 糖果 有 拿和不拿两种状态 , 所以需要使用 背包

同时,又因为 需要 表示当前状态 ,所以考虑使用 状态压缩

状态表示 :
d p [ N ] [ 1 < < M ] dp[N][1<<M] dp[N][1<<M] 表示 从前 i i i袋糖果选,状态为 s s s的最小集合

状态计算 :
d p [ i ] [ s ] = m i n ( d p [ i ] [ s ] , d p [ i − 1 ] [ s & ( − w [ i ] ) ] + 1 ) ( − w [ i ] 表 示 按 位 取 反 , L a t e x 打 不 出 来 dp[i][s] =min(dp[i][s],dp[i-1][s\&(-w[i])]+1)(-w[i]表示按位取反,Latex打不出来 dp[i][s]=min(dp[i][s],dp[i1][s&(w[i])]+1)(w[i],Latex

因为 N = 100 N=100 N=100 ,因为空间开销 2 20 ∗ N 2^{20}*N 220N 会寄

所以考虑优化 1 1 1维,当然我们跟着 背包 倒序转移即可

Mycode

// Problem: 糖果
// Contest: AcWing
// URL: https://www.acwing.com/problem/content/1245/
// Memory Limit: 64 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <iostream>
#include <vector>
#include <map>
#include <cstring>
#include <queue>
#include <set>
#include <algorithm>
using namespace std;
#define IOS  ios::sync_with_stdio(false);
#define CIT  cin.tie(0);
#define COT  cout.tie(0);

#define ll long long
#define x first
#define y second
#define pb push_back
#define endl '\n'
#define all(x) (x).begin(),x.end()
#define Fup(i,a,b) for(int i=a;i<=b;i++)
#define Fde(i,a,b) for(int i=a;i>=b;i--)

typedef priority_queue<int,vector<int>,greater<int>>  Pri_m;
typedef pair<int,int> pii;
typedef vector<int> VI;
map<int,int> mp;
const int N = 110,M  =(1<<20)+10 , INF = 0x3f3f3f3f;
int w[N],f[M],n,m,k;

void solve(){
	cin>>n>>m>>k;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=k;j++){
			int x;cin>>x;
			w[i]|=  1<<x-1;
		}
	}
	
	memset(f,0x3f,sizeof f);
	f[0] = 0 ;
	for(int i=1;i<=n;i++)
		for(int s = (1<<m);s>0;s--)
		f[s] = min(f[s],f[s&(~w[i])]+1);
		
	if(f[(1<<m)-1] == INF)cout<<-1<<endl;
	else cout<<f[(1<<m)-1]<<endl;
	
}

int main(){
    //int t;cin>>t;while(t--)
    solve();
    return 0 ;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
import xlrd def result_write(result,i,j):#result为txt文件,i为比赛项目,j为奖项等级 tmp_str='' tmp_num=0 if award_dict[i][j][0]!=0: result.write(j+'获奖人数为'+str(award_dict[i][j][0])+'人,姓名如下:\n') else: result.write(j+'获奖人数为0人\n') for j in award_dict[i][j][1:]: tmp_str+=j tmp_str+=' ' tmp_num+=1 if tmp_num==10:#每十人写入文件并换行 result.write(tmp_str+'\n') tmp_str='' tmp_num=0 if tmp_num!=0:#向文件写入不满十人的姓名组 result.write(tmp_str+'\n') result.write('\n') award_dict=dict() data= xlrd.open_workbook("C:\\Users\\游雏\\Downloads\\2022蓝桥江西省赛.xls") sheet1 = data.sheet_by_name("Sheet1") col = sheet1.col_values(4) award_class=[] for i in col[1:]:#获取比赛项目列表,首字母统一大写 if 'a'<=i[0]<='z': i=i[0].upper()+i[1:] if i not in award_class: award_class.append(i) for i in award_class:#创建一个嵌套字典,一级字典以比赛项目为键,二级字典以奖项等级为键,值为获奖人姓名列表 award_dict[i]=dict(一等奖=[0],二等奖=[0],三等奖=[0]) for i in range(sheet1.nrows):#按行遍历表格 if i==0:continue row = sheet1.row_values(i) if row[2]=='江西理工大学':#row[2]为学校名 if 'a'<=row[4][0]<='z':#row[4]为比赛项目 row[4]=row[4][0].upper()+row[4][1:] award_dict[row[4]][row[5]][0]+=1#统计某项目某奖项的获奖人数,row[5]为奖项等级 award_dict[row[4]][row[5]].append(row[3])#将获奖者姓名添入一级键为项目二级键为奖项的列表,row[3]为获奖者姓名 award_level=['一等奖','二等奖','三等奖'] result=open("resutl.txt", "w") for i in award_class: result.write(i+'\n') for j in award_level: result_write(result,i,j) result.write('\n') result.close()帮我优化此代码
05-27
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值