CH0103
状压dp
核心思想:状压DP,列举当前状态存在所有相连路径来更新最短路径
#include<iostream>
#include<cstdio>
#include<cmath>
#include<vector>
#include<algorithm>
#include<string>
#include<cstring>
#define inf 0x3f3f3f
using namespace std;
int dp[(1<<22)][21];//表第一维状压表示现在的状态,第二维表示到该点的最短距离
int len[21][21];
int main (){
int n;
cin>>n;
for(int i=0; i<n; i++) {
for(int j=0; j<n; j++) {
cin>>len[i][j];
}
}
memset(dp,inf,sizeof(dp));
dp[1][0]=0;
for(int i=1; i<=(1<<n)-1; i++) { //遍历所有状态
for(int j=0; j<n; j++) { //遍历该状态里所有点
if((i>>j)&1) { //若该状态中第j个点走过
for(int k=0; k<n; k++) {
if((i>>k)&1) {
dp[i][j]=min(dp[i][j],dp[i^(1<<j)][k]+len[j][k]);
}
}
}
}
}
cout<<dp[(1<<n)-1][n-1];
return 0;
}
/*
4
0 2 1 3
2 0 2 1
1 2 0 1
3 1 1 0
*/
CH0104
核心思想:由于位运算不进位,所以可以一位一位进行操作,因此直接枚举答案的每一位进行操作后,再贪心一下
#include<iostream>
#include<cstdio>
#include<cmath>
#include<vector>
#include<algorithm>
#include<string>
#include<cstring>
using namespace std;
int n,m;
int a[100010];
string st[100010];
int change(int c,int b){
for(int i=0;i<n;i++){
if(st[i]=="AND") b&=a[i]>>c&1;
else if(st[i]=="OR") b|=a[i]>>c&1;
else b^=a[i]>>c&1;
}
return b;
}
int main(){
ios::sync_with_stdio(0),cin.tie(0);
cin>>n>>m;
string s;
for(int i=0;i<n;i++){
cin>>s;
st[i]=s;
cin>>a[i];
}
int d=0;//当前数值,不能超过m
int ans=0;
int case_1,case_0;
for(int i=29;i>=0;i--){//取值范围的二进制最多29位
case_1=change(i,1);
case_0=change(i,0);
//cout<<i<<" "<<case_0<<" ^^^ "<<case_1<<endl;
if(d+(1<<i)<=m&&case_0<case_1){
d+=1<<i;
ans+= case_1<<i;
}else{
ans+= case_0<<i;
}
}
cout<<ans;
return 0;
}
CH0301
普通的递归
#include<iostream>
#include<cstdio>
#include<cmath>
#include<vector>
#include<algorithm>
#include<string>
#include<cstring>
using namespace std;
int n;
vector<int> ans;
void find(int x){
if(x==n+1){
for(int i=0;i<ans.size() ;i++){
cout<<ans[i]<<" ";
}
cout<<endl;
return;
}
find(x+1);
ans.push_back(x) ;
find(x+1);
ans.pop_back() ;
}
int main(){
cin>>n;
find(1);
return 0;
}
CH0302
思路:个数有限定,所以不合题意的分支可以直接剪枝
#include<iostream>
#include<cstdio>
#include<cmath>
#include<vector>
#include<algorithm>
#include<string>
#include<cstring>
using namespace std;
int n,m;
vector<int> ans;
void find(int x){
if(ans.size() >m||ans.size() +(n-x+1)<m){
return ;
}
if(x==n+1){
for(int i=0;i<ans.size() ;i++){
cout<<ans[i]<<" ";
}
cout<<endl;
return;
}
ans.push_back(x) ;
find(x+1);
ans.pop_back() ;
find(x+1);
}
int main(){
cin>>n>>m;
find(1);
return 0;
}
CH0303
思路:普通递归
#include<iostream>
#include<cstdio>
#include<cmath>
#include<vector>
#include<algorithm>
#include<string>
#include<cstring>
using namespace std;
int n;
int b[50];
int ord[50];
void find(int x){
if(x==n+1){
for(int i=1;i<=n;i++){
cout<<ord[i]<<" ";
}
cout<<endl;
return ;
}
for(int i=1;i<=n;i++){
if(!b[i]){
ord[x]=i;
b[i]=1;
find(x+1);
b[i]=0;
}
}
}
int main(){
cin>>n;
find(1);
return 0;
}