康复训练 Day2

洛谷2962:

dfs折半搜索。。主要得想到用二进制数来代表开关状态,看了题解才想起来(还是菜啊

# include <iostream>
# include <cstdio>
# include <cstring>
# include <cmath>
# include <list>
# include <map>
# include <queue>
# include <algorithm>
# include <set>
#define maxn 105
using namespace std;
int read(){
	register int f=1,i=0;char ch=getchar();
	while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9') {i=(i<<3)+(i<<1)+ch-'0';ch=getchar();}
	return f*i;
}

typedef long long ll;
int n,m,num[maxn],dest,half,ans=maxn,pre=0;
ll bin[maxn],light[maxn],temp[maxn];
map<ll,int>vis;

void Dfs(int t,int state,int num)
{
	if(t>half){
		if(!pre){
			if(!vis[state]) vis[state]=num;
			else vis[state]=min(vis[state],num);
		}
		else if(vis[state^dest]) ans=min(ans,num+vis[state^dest]);
		return ;
	} 
	Dfs(t+1,state^temp[t],num+1);
	Dfs(t+1,state,num);
}
int main(){
	//freopen("lx.in","r",stdin);
	n=read(),m=read();
	bin[0]=1;
	for(int i=1;i<=n;++i) bin[i]=bin[i-1]<<1;
	dest=bin[n]-1;
	for(int i=1,x,y;i<=m;++i){
		x=read(),y=read();
		light[x]^=bin[y-1];
		light[y]^=bin[x-1];
	}
	for(int i=1;i<=n;++i) light[i]^=bin[i-1];
	memset(temp,0,sizeof(temp));
	half=(n+1)>>1;
	for(int i=1;i<=half;++i) temp[i]=light[i];
	Dfs(1,0,0);
	for(int i=1;i<=half;++i) temp[i]=light[i+half];
	pre=1;
	Dfs(1,0,0);
	cout<<ans<<endl;
	return 0;
} 

Dp复习:

最长公共子序列:

#include<bits/stdc++.h>
#define maxn 100005
using namespace std;

int read(){
	register int f=1,i=0;char ch=getchar();
	while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9') {i=(i<<3)+(i<<1)+ch-'0';ch=getchar();}
	return f*i;
}

int f[maxn],n,a[maxn],b[maxn],tot[maxn];
int main()
{
    freopen("lx.in","r",stdin);
	n=read();
    for(int i=1;i<=n;++i) a[i]=read(),tot[a[i]]=i;
    for(int i=1;i<=n;++i) b[i]=read();
    for(int i=1;i<=n;++i) f[i]=INT_MAX;
	for(int i=1;i<=n;++i) *upper_bound(f+1,f+n+1,tot[b[i]])=tot[b[i]];
	int ans=0;
	while(f[++ans]!=INT_MAX);
	cout<<ans-1<<endl;
	return 0;  
} 

采药:

记搜水题,dp还是太难搞了,能写记搜就记搜吧

# include <iostream>
# include <cstdio>
# include <cstring>
# include <cmath>
# include <list>
# include <map>
# include <queue>
# include <algorithm>
# include <set>
#define maxn 100005
using namespace std;

int read(){
	register int f=1,i=0;char ch=getchar();
	while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9') {i=(i<<3)+(i<<1)+ch-'0';ch=getchar();}
	return f*i;
}

struct Node{
	int tim,val;
}herb[maxn];
int n,m,T,ans=0,dp[105][1005];

int Dfs(int pos,int left)
{
	if(dp[pos][left]!=-1) return dp[pos][left];
	if(pos==m+1) return 0;
	int res1=-1,res2=-1;
	res1=Dfs(pos+1,left);
	if(left>=herb[pos].tim) res2=Dfs(pos+1,left-herb[pos].tim)+herb[pos].val;
	return dp[pos][left]=max(res1,res2);
}
int main()
{
	freopen("lx.in","r",stdin);
	T=read(),m=read();
	for(int i=1;i<=m;++i) herb[i].tim=read(),herb[i].val=read();
	memset(dp,-1,sizeof(dp)); 
	cout<<Dfs(1,T)<<endl;
    return 0;
}

洛谷1880:

合并石子,区间dp经典水题,同样写记搜。。

# include <iostream>
# include <cstdio>
# include <cstring>
# include <cmath>
# include <list>
# include <map>
# include <queue>
# include <algorithm>
# include <set>
#define maxn 205
using namespace std;

int read(){
	register int f=1,i=0;char ch=getchar();
	while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9') {i=(i<<3)+(i<<1)+ch-'0';ch=getchar();}
	return f*i;
}

int n,a[maxn],sum[maxn],dp_1[maxn][maxn],dp_2[maxn][maxn];

int Dfs1(int l,int r)
{
	if(dp_1[l][r]!=-1) return dp_1[l][r];
	if(l==r) return dp_1[l][r]=0;
	int res=0x7fffff;
	for(int i=l;i<r;++i){
		res=min(res,Dfs1(l,i)+Dfs1(i+1,r)+sum[r]-sum[l-1]);
	} 
	return dp_1[l][r]=res;
}

int Dfs2(int l,int r)
{
	if(dp_2[l][r]!=-1) return dp_2[l][r];
	if(l==r) return dp_2[l][r]=0;
	int res=0;
	for(int i=l;i<r;++i){
		res=max(res,Dfs2(l,i)+Dfs2(i+1,r)+sum[r]-sum[l-1]);
	} 
	return dp_2[l][r]=res;
}
int main()
{
	freopen("lx.in","r",stdin);
	n=read();
	memset(sum,0,sizeof(sum));
	memset(dp_1,-1,sizeof(dp_1));
	memset(dp_2,-1,sizeof(dp_2));
	for(int i=1;i<=n;++i) a[i]=read(),a[i+n]=a[i];
	for(int i=1;i<=(n<<1);++i) sum[i]=sum[i-1]+a[i];
	Dfs1(1,n<<1);
	Dfs2(1,n<<1);
	int ans_1=0x7ffffff,ans_2=0;
	for(int i=1;i<=n;++i){
		ans_1=min(ans_1,dp_1[i][i+n-1]);
		ans_2=max(ans_2,dp_2[i][i+n-1]);
	}
	cout<<ans_1<<endl<<ans_2<<endl;
	return 0;
}

洛谷3205:

区间dp水题,老规矩记搜。。dp是不可能dp的。

# include <iostream>
# include <cstdio>
# include <cstring>
# include <cmath>
# include <list>
# include <map>
# include <queue>
# include <algorithm>
# include <set>
#define maxn 1005
using namespace std;

int read(){
	register int f=1,i=0;char ch=getchar();
	while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9') {i=(i<<3)+(i<<1)+ch-'0';ch=getchar();}
	return f*i;
}

const int mod=19650827;
int n,a[maxn],f[maxn][maxn][5];

int Dfs(int l,int r,int insert)
{
	if(f[l][r][insert]!=-1) return f[l][r][insert];
	if(l==r) return insert==0 ? f[l][r][insert]=1:f[l][r][insert]=0;
	int res=0;
	if(!insert){
		if(a[l]<a[l+1]) res+=Dfs(l+1,r,0);
		if(a[l]<a[r]) res+=Dfs(l+1,r,1);
		res%=mod;
	}
	else{
		if(a[r]>a[l]) res+=Dfs(l,r-1,0);
		if(a[r]>a[r-1]) res+=Dfs(l,r-1,1);
		res%=mod;
	}
	return f[l][r][insert]=res;
}
int main()
{
	freopen("lx.in","r",stdin);
	n=read();
	memset(f,-1,sizeof(f));
	for(int i=1;i<=n;++i) a[i]=read();
    int ans=0;
    ans+=(Dfs(1,n,0)+Dfs(1,n,1))%mod;
    cout<<ans<<endl;
	return 0;
}

洛谷1063:

区间dp,水题,还是写记搜。。

#include<bits/stdc++.h>
using namespace std;

vector<pair<int,int> >q;
int n,a[1005],f[2005][2005]; 
int Dfs(int l,int r)
{
    if(f[l][r]!=-1) return f[l][r];	
    if(l==r) return f[l][r]=0;
    int res=0;
    for(int k=l;k<r;++k) res=max(res,Dfs(l,k)+Dfs(k+1,r)+q[(l-1)%n].first*q[k%n].first*q[(r-1)%n].second);
    return f[l][r]=res;
} 
int main()
{
    freopen("lx.in","r",stdin);
	cin>>n;
	memset(f,-1,sizeof(f));
    for(int i=1;i<=n;++i) cin>>a[i];
    for(int i=1;i<=n;++i)
    {
    	int l=a[i],r=a[i+1];
    	if(i==n) r=a[1];
		q.push_back(make_pair(l,r)); 
	}
	//cout<<q[0].first*q[1].first*q[1].second<<endl;
	int t=Dfs(1,n<<1);
    int ans=0;
    for(int i=1;i<=(n<<1);++i) ans=max(ans,f[i][i+n-1]);
	cout<<ans<<endl; 
	return 0;
}

洛谷1020:

最长不下降和最长上升序列,注意写法:

# include <iostream>
# include <cstdio>
# include <cstring>
# include <cmath>
# include <list>
# include <map>
# include <queue>
# include <algorithm>
# include <set>
#define maxn 1000005
using namespace std;
int read(){
	register int f=1,i=0;char ch=getchar();
	while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9') {i=(i<<3)+(i<<1)+ch-'0';ch=getchar();}
	return f*i;
}
const int Inf=0x7fffffff;
int x,cnt=0,a[maxn],b[maxn],f1[maxn],f2[maxn];
int main(){
//	freopen("lx.in","r",stdin);
	while(scanf("%d",&x)!=EOF) a[++cnt]=x;
	for(int i=1;i<=cnt;++i) b[cnt-i+1]=a[i];
	f1[1]=b[1];
	f2[1]=a[1];
	int ans1=1,ans2=1;
    for(int i=2;i<=cnt;++i) {
   	    if(b[i]>=f1[ans1]) f1[++ans1]=b[i];
   	    else f1[upper_bound(f1+1,f1+ans1+1,b[i])-f1]=b[i];
   	    if(a[i]>f2[ans2]) f2[++ans2]=a[i];
   	    else f2[lower_bound(f2+1,f2+ans2+1,a[i])-f2]=a[i];
	}
    cout<<ans1<<endl<<ans2;
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值