洛谷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;
}