今天早上的题都是搜索。
第一题:给出n个开关,一个开关对应一个灯,灯与灯之间有连边,当摁下一个开关时,对应的灯和相邻的灯都会改变状态,问至少摁下多少开关,才可以把所有灯打开。
这道题很容易就可以想到一个结论:一个开关只会被打开一次,打开两次没有影响。
就可以直接爆搜拿到60分。满分也很简单,我们折半搜索,把第一次搜索的结果存在一个map里面,总共只会有种情况。然后在搜索第二次搜索的结果取反放进第一次搜索的结果里面找,然后用和的最小值更新答案就好了。
#include
#include
#include
#include
#include
第二题:给出一个长度为n的排列,每次可以把1到i翻转,问最少用多少此操作可以把出事排列变为1到n。
这题我只会暴力,可以把状态记录下来,然后bfs,可以很容易知道一个排列在字典序的第几位。那么就直接做就可以拿到比暴力分稍多一点的40分。
然而正解很神仙,首先是迭代加深,关键就加一个可行性剪枝,预估当前状态到答案还要多少步,如果用当前步数+至少需要的步数>规定步数,那么直接return ; 那么这个预估怎么做呢,可以发现,当我们在翻转1到i时,相邻两位之差的改变只有一对。
可以发现,1到n这个排列相邻两位差没有不为1的。所以我们可以把预估步数直接设为相邻两位之差不为1的对数。
但是n到1这个排列它相邻两位之差不为1的对数也没有。所以我们可以加上第0位与第1位之差。
这样可能导致最后一次翻转会改变2对,所以我们把限制放宽就好了。
#include
#include
#include
#include
using namespace std;
int n;
int a[25];
bool we=false;
void dfs(int x,int mmax,int*a,int ty){
if(x+ty-2>mmax) return ;
if(x==mmax+1){
if(ty==0) we=true;
return ;
}
for(int i=2;i<=n;i++){
ty-=(abs(a[1]-a[0])!=1);if(i!=n) ty-=(abs(a[i]-a[i+1])!=1);
for(int j=1;j<=i/2;j++) swap(a[j],a[i-j+1]);
ty+=(abs(a[1]-a[0])!=1);if(i!=n) ty+=(abs(a[i]-a[i+1])!=1);
dfs(x+1,mmax,a,ty);
if(we) return ;
ty-=(abs(a[1]-a[0])!=1);if(i!=n) ty-=(abs(a[i]-a[i+1])!=1);
for(int j=1;j<=i/2;j++) swap(a[j],a[i-j+1]);
ty+=(abs(a[1]-a[0])!=1);if(i!=n) ty+=(abs(a[i]-a[i+1])!=1);
}
}
int main(){
scanf("%d",&n);int tot=0;
for(int i=1;i<=n;i++) {
scanf("%d",&a[i]);
tot+=(abs(a[i]-a[i-1])!=1);
}
int tar=1;
while(1){
dfs(1,tar,a,tot);
if(we) {printf("%d",tar);return 0;}
tar++;
}
}
第三题:有m个武器,n个炸弹,第i个武器可以攻击当且仅当前i-1个武器被消灭。给出m个武器与n个炸弹的坐标,一个炸弹可以消灭周围平面距离不超过k且正在攻击的武器,武器的切换用时1秒钟,一个炸弹连续攻击5分钟。现在,要你安排n个炸弹的顺序,问你用最少多少个炸弹可以消灭全部的武器。
很容易就可以发现一个炸弹可以攻击周围的连续炸弹,假若当前在攻击的炸弹为i,i~T都在炸弹的攻击范围内,那么下一个攻击的武器就一定是T+1。这个十分的明显。
利用这个我们可以给这张图建边,边权就是用的炸弹。然后我们可以忽略每个炸弹的限制,从m+1这个点走反边跑一遍bfs。那么我们就知道在搜索时答案的下界,就可以进行最优性剪枝了。
但是不知道为什么,改了之后后面5个点还是过不了。
#include
#include
#include
#include
#include
#include
using namespace std;
int m,n,k;
struct node{
int x,y;
}a[110],b[110];
struct pre{
int x,y,c;
bool operator<(const pre a)const{
return y-x=ans) return ;
if(now==m+1){
ans=x-1;
printf("%d\n",ans);
return ;
}
for(int i=first[now];i!=0;i=s[i].next){
if(tf[s[i].c]) continue;
tf[s[i].c]=true;
dfs(x+1,s[i].y);
tf[s[i].c]=false;
}
}
int main(){
scanf("%d %d %d",&m,&n,&k);
for(int i=1;i<=m;i++) scanf("%d %d",&a[i].x,&a[i].y);
for(int i=1;i<=n;i++) scanf("%d %d",&b[i].x,&b[i].y);
for(int i=1;i<=n;i++){
memset(tf,false,sizeof(tf));
for(int j=1;j<=m;j++) if(get_dis(b[i],a[j])+eps<=k) tf[j]=true;
int tot=0;
for(int j=1;j<=m+1;j++){
if(!tf[j]){
for(int k=j-tot;k<=j-1;k++) p[++t]=(pre){k,j,i},inss(j,k);
tot=0;continue;
}
tot++;
}
}
sort(p+1,p+1+t);
for(int i=1;i<=t;i++) ins(p[i].x,p[i].y,p[i].c);
bfs();
memset(tf,false,sizeof(tf));
dfs(1,1);
printf("%d\n",ans);
}