今天想了一下午+一晚上二分,终于想明白了,深深的被二分疑惑到了,所以lower_bound和upper_bound等等能手写的全手写了,哈哈哈哈哈。
1.拦截导弹
题目链接
这里是非dp写法,用的贪心写法,比较巧妙
手写了俩lower_bound和upper_bound函数
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1010;
int f[N],g[N];
int len=0,cnt=0;
int find1(int x)
{
int l=0,r=len;
while(l<r)
{
int mid=l+r>>1;
if(f[mid]>=x)l=mid+1;
else r=mid;
}
return r;
}
int find2(int x)
{
int l=0,r=cnt;
while(l<r)
{
int mid=l+r>>1;
if(g[mid]>=x)r=mid;
else l=mid+1;
}
return r;
}
int main()
{
int x;
while(cin>>x)
{
//int pos1=find1(x);
int pos1=upper_bound(f,f+len,x,greater<int>())-f;
if(pos1==len)f[len++]=x;
else f[pos1]=x;
//int pos2=find2(x);
int pos2=lower_bound(g,g+cnt,x)-g;
if(pos2==cnt)g[cnt++]=x;
else g[pos2]=x;
}
cout<<len<<endl;
cout<<cnt<<endl;
}
2.导弹防御系统
解一:dfs迭代加深+贪心
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 55;
int up[N],down[N];
int n;
int a[N];
bool dfs(int depth,int u,int su,int sd)
{
if(su+sd>depth)return false;
if(u==n)return true;
bool flag=false;
for(int i=1;i<=su;i++)
{
if(up[i]>a[u])
{
int t=up[i];
up[i]=a[u];
if(dfs(depth,u+1,su,sd))return true;
up[i]=t;
flag=true;
break;
}
}
if(!flag){
up[su+1]=a[u];
if(dfs(depth,u+1,su+1,sd))return true;
}
flag=false;
for(int i=1;i<=sd;i++)
{
if(down[i]<a[u])
{
int t=down[i];
down[i]=a[u];
if(dfs(depth,u+1,su,sd))return true;
down[i]=t;
flag=true;
break;
}
}
if(!flag)
{
down[sd+1]=a[u];
if(dfs(depth,u+1,su,sd+1))return true;
}
return false;
}
int main()
{
while(cin>>n,n)
{
for(int i=0;i<n;i++)cin>>a[i];
int depth=0;
while(!dfs(depth,0,0,0))depth++;
cout<<depth<<endl;
}
}
进阶版迭代加深dfs+贪心
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 55;
int up[N],down[N];
int n;
int a[N];
int find1(int x,int su)
{
int l=1,r=su+1;
while(l<r)
{
int mid=l+r>>1;
if(up[mid]>=x)l=mid+1;
else r=mid;
}
return r;
}
int find2(int x,int sd)
{
int l=1,r=sd+1;
while(l<r)
{
int mid=l+r>>1;
if(down[mid]<=x)l=mid+1;
else r=mid;
}
return r;
}
bool dfs(int depth,int u,int su,int sd)
{
if(su+sd>depth)return false;
if(u==n)return true;
int pos1=find1(a[u],su);
if(pos1<=su)
{
int t=up[pos1];
up[pos1]=a[u];
if(dfs(depth,u+1,su,sd))return true;
up[pos1]=t;
}
else
{
up[su+1]=a[u];
if(dfs(depth,u+1,su+1,sd))return true;
}
int pos2=find2(a[u],sd);
if(pos2<=sd)
{
int t=down[pos2];
down[pos2]=a[u];
if(dfs(depth,u+1,su,sd))return true;
down[pos2]=t;
}
else
{
down[sd+1]=a[u];
if(dfs(depth,u+1,su,sd+1))return true;
}
return false;
}
int main()
{
while(cin>>n,n)
{
for(int i=0;i<n;i++)cin>>a[i];
int depth=0;
while(!dfs(depth,0,0,0))depth++;
cout<<depth<<endl;
}
}
解法二:
全局变量dfs+贪心写法
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 55;
int n;
int h[N];
int up[N], down[N];
int ans;
void dfs(int u, int su, int sd)
{
if (su + sd >= ans) return;
if (u == n)
{
ans = min(ans, su + sd);
return;
}
int k = 0;
// while (k < su && up[k] >= h[u]) k ++ ;
k = upper_bound(up, up + su, h[u], greater<int>()) - up;
if (k < su)
{
int t = up[k];
up[k] = h[u];
dfs(u + 1, su, sd);
up[k] = t;
}
else
{
up[k] = h[u];
dfs(u + 1, su + 1, sd);
}
k = 0;
// while (k < sd && down[k] <= h[u]) k ++ ;
k = upper_bound(down, down + sd, h[u]) - down;
if (k < sd)
{
int t = down[k];
down[k] = h[u];
dfs(u + 1, su, sd);
down[k] = t;
}
else
{
down[k] = h[u];
dfs(u + 1, su, sd + 1);
}
}
int main()
{
while (cin >> n, n)
{
for (int i = 0; i < n; i ++ ) cin >> h[i];
ans = n;
dfs(0, 0, 0);
cout << ans << endl;
}
return 0;
}