解题报告
前言
这一次主要讲的是关于深搜
洛谷 1457 城堡 The Castle
洛谷 1458 顺序的分数 Ordered Fractions
题目
输入一个自然数 N N N,对于一个最简分数 a b , g c d ( a , b ) = 1 \frac{a}{b},gcd(a,b)=1 ba,gcd(a,b)=1,满足 1 ≤ b ≤ N , 0 ≤ a / b ≤ 1 1\leq b\leq N,0\leq a/b\leq 1 1≤b≤N,0≤a/b≤1,请递增输出所有满足条件的分数。
分析
然而这道题特别神奇,若 a b < c d , a < c , b < d , 那 么 a b < a + c b + d < c d \frac{a}{b}<\frac{c}{d},a<c,b<d,那么\frac{a}{b}<\frac{a+c}{b+d}<\frac{c}{d} ba<dc,a<c,b<d,那么ba<b+da+c<dc,所以可以通过分治实现,可惜我貌似不会证明
代码
/*
ID:lemond1
LANG:C++
TASK:frac1
*/
#include <cstdio>
using namespace std;
int n;
void dfs(int a,int b,int c,int d){
if (a+c>n||b+d>n) return;
dfs(a,b,a+c,b+d);
printf("%d/%d\n",a+c,b+d);
dfs(a+c,b+d,c,d);
}
signed main(){
freopen("frac1.in","r",stdin);
freopen("frac1.out","w",stdout);
scanf("%d",&n);
printf("%d/%d\n",0,1);
dfs(0,1,1,1);
printf("%d/%d\n",1,1);
return 0;
}
洛谷 1459 三值的排序 Sorting a Three-Valued Sequence
题目
由1,2,3组成的无序序列,排成升序的最少交换次数
分析
也就是说,只要把1和2排好,那么3也可以排出来,所以答案就是变成1的个数+变成2的个数-互变的个数
代码
/*
ID:lemondi1
LANG:C++
TASK:sort3
*/
#include <cstdio>
#define rr register
using namespace std;
int flag1,flag2,a[1001],n,ans,swap1,swap2;
signed main(){
freopen("sort3.in","r",stdin);
freopen("sort3.out","w",stdout);
scanf("%d",&n);
for (rr int i=1;i<=n;++i) scanf("%d",&a[i]);
for (rr int i=1;i<=n;++i)
flag1+=a[i]==1,flag2+=a[i]==2;
for (rr int i=1;i<=n;++i){
if (a[i]!=1&&i<=flag1) ++ans;//原来不是1变成1
if (a[i]!=2&&i>flag1&&i<=flag1+flag2) ++ans;//原来不是2变成2
if (a[i]==2&&i<=flag1) ++swap1;//原来是2变成1
if (a[i]==1&&i>flag1&&i<=flag1+flag2) ++swap2;//原来是1变成2
}
ans-=(swap1<swap2)?swap1:swap2;//减最小值
return !printf("%d\n",ans);
}
洛谷 1460 健康的荷斯坦奶牛 Healthy Holsteins
分析
既然要字典序,那么深搜判断,其实也是比较简单的,但是饲料数不可兼得,只能判断
代码
/*
ID:lemondi1
LANG:C++
TASK:holstein
*/
#include <cstdio>
#define min(a,b) ((a)<(b))?(a):(b)
#define rr register
using namespace std;
int n,minx,ans,now,a[31],f[21][31],m;
inline signed in(){
rr int ans=0; rr char c=getchar();
while (c<48||c>57) c=getchar();
while (c>47&&c<58) ans=(ans<<3)+(ans<<1)+c-48,c=getchar();
return ans;
}
void print(int ans){
if (ans>9) print(ans/10);
putchar(ans%10+48);
}
signed pd(){
for (rr int i=1;i<=n;++i) if (a[i]>0) return 0;
return 1;
}
void dfs(int dep,int t){
if (t>=minx) return;//不可能再得到最优解
if (pd()){ans=now; minx=t; return;}//判断成功
if (dep>m) return;//搜完了
for (rr int i=1;i<=n;++i) a[i]-=f[dep][i]; now|=1<<dep-1;
dfs(dep+1,t+1);
for (rr int i=1;i<=n;++i) a[i]+=f[dep][i]; now^=1<<dep-1;
dfs(dep+1,t);
}
signed main(){
freopen("holstein.in","r",stdin);
freopen("holstein.out","w",stdout);
n=in(); for (rr int i=1;i<=n;++i) a[i]=in();
m=in(); minx=m+1;
for (rr int i=1;i<=m;++i)
for (rr int j=1;j<=n;++j) f[i][j]=in();
dfs(1,0); print(minx);
for (rr int i=1;i<=m;++i) if (ans&(1<<i-1)) putchar(32),print(i);
return !putchar(10);
}
洛谷 1461 海明码 Hamming Codes
分析
从0开始枚举,每当与前面的海明码异或后1的个数 < d <d <d时,则该数不是海明码
代码
/*
ID:lemondi1
LANG:C++
TASK:hamming
*/
#include <cstdio>
#define min(a,b) ((a)<(b))?(a):(b)
#define rr register
using namespace std;
int n,d,ans[65],len=1;
void print(int ans){
if (ans>9) print(ans/10);
putchar(ans%10+48);
}
signed count(int x){//计算二进制下1的个数
rr int ans=0;
while (x) ++ans,x&=x-1;
return ans;
}
signed main(){
freopen("hamming.in","r",stdin);
freopen("hamming.out","w",stdout);
scanf("%d%*d%d",&n,&d); putchar(48);
for (rr int j=1,len=1;len<n;++j){
rr int flag=1;
for (rr int i=1;i<=len;++i) if (count(ans[i]^j)<d) flag=0;
if (flag) ans[++len]=j,putchar(len%10==1?'\n':' '),print(j);
}
return !putchar(10);
}
后续
未完待续