1 条题解
-
0
自动搬运
来自洛谷,原作者为

jun头吉吉
alive搬运于
2025-08-24 21:40:37,当前版本为作者最后更新于2020-07-04 12:56:54,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
一道
简单的模拟题首先我们来看一下题面

??? 图呢

根据我们的生活经验,我们知道应该是这么摆的:

首先我们发现,题目中不能移动构成运算符(+、-、=)的木棒 ,因此我们不管怎么移动数字的木棒,这个数的加、减和位数是不变的。我们如果把所有的数字都按照位数拆开来,以样例为例
11+77=34变成
1*10+1*1+7*10+7*1=3*10+4*1那么不管数字怎么变,它后面乘的多少是不会变的,因此我们可以提前处理好。然而在等号两边让我们看起来很不爽,反正符号不会变,我们可以通过初中知识移项将其全部移到一遍就ok了
1*10+1*1+7*10+7*1-3*10-4*1=0那我们现在只需要通过更改上式中任意两个第一项使其成立就做完了
我们知道,因此我们完全可以枚举两个数,然后考虑移动火柴带来的情况,在判断是否成立
由于我比较懒,用了一种常数较大的算法,即选一个有火柴的地方,在选取一个没有火柴的地方,移动火柴,判断式子是否成立(其实这么做枚举了很多不必要的情况)
对于一个数字,选择用状压去描述,如果有第根火柴,二进制下第位就是,反之为
当对第根火柴进行更改时,就把数字即可
具体实现可以参考代码
#include<bits/stdc++.h> char ch[2000]; const int n[10]={0b1111011,//0 0b1001000,//1 0b0111101,//2 0b1101101,//3 0b1001110,//4 0b1100111,//5 0b1110111,//6 0b1001001,//7 0b1111111,//8 0b1101111//9 }; struct num{//数字 int val;//权值 int des;//描述 /* _ 1 |_| 2 3 4 |_| 5 6 7 */ /* 7 6 5 4 3 2 1 1 4 7 1 0 0 1 0 0 0 2 1 3 4 5 6 0 1 1 1 1 0 1 3 1 3 4 6 7 1 1 0 1 1 0 1 4 2 3 4 7 1 0 0 1 1 1 0 5 1 2 3 6 7 1 1 0 0 1 1 1 6 1 2 3 5 6 7 1 1 1 0 1 1 1 7 1 4 7 1 0 0 1 0 0 1 8 1 2 3 4 5 6 7 1 1 1 1 1 1 1 9 1 2 3 4 6 7 1 1 0 1 1 1 1 0 1 2 4 5 6 7 1 1 1 1 0 1 1 */ bool check(){//检验是否合法 for(int i=0;i<10;i++) if(val==n[i]) return true; return false; } bool check(int w){//检验第w根是否存在 if(val>>w&1!=0)return true; return false; } bool change(int w){//更改w根的位置 val^=(1<<w); } int get(){ for(int i=0;i<10;i++) if(val==n[i]) return i; } num(int _N=0,int Wi=0,int type=0){//_N表示数值 Wi表示位置 val=n[_N]; des=type*pow(10,Wi); } }a[2000]; bool check(num *t,int L){//检查 int num=0; for(int i=1;i<=L;i++){ if(!t[i].check())return false; num+=t[i].des*t[i].get(); } return num==0; } int tot=0; signed main(){ //freopen("t.in","r",stdin); int len=0,eq=1; while(true){ ch[++len]=getchar(); if(ch[len]=='#')break; } while(ch[eq]!='=')eq++; //分别处理等号前后 //把右边的等价到左边 for(int i=len-1,j;i>eq;i=j-1){ j=i; while(j-1>0&&isdigit(ch[j-1]))j--; int type=-1; if(ch[j-1]=='-')type=1; for(int w=i;w>=j;w--) a[++tot]=num(ch[w]-'0',i-w,type); if(ch[j-1]=='+'||ch[j-1]=='-')j--; } for(int i=eq-1,j;i>=1;i=j-1){ j=i; while(j-1>0&&isdigit(ch[j-1]))j--; int type=1; if(ch[j-1]=='-')type=-1; for(int w=i;w>=j;w--) a[++tot]=num(ch[w]-'0',i-w,type); if(ch[j-1]=='+'||ch[j-1]=='-')j--; } //for(int i=1;i<=tot;i++) // printf("%d*%d ",a[i].get(),a[i].des); check(a,tot); for(int i=1;i<=tot;i++) for(int j=0;j<8;j++)//枚举拿走的火柴 if(a[i].check(j)) for(int w=1;w<=tot;w++) for(int k=0;k<8;k++) if(!a[w].check(k)){ //将i的j放到w的k上 a[i].change(j); a[w].change(k); if(check(a,tot)){ int p=tot; for(int i=1;i<=len;i++) if(isdigit(ch[i]))putchar(a[p--].get()+'0'); else putchar(ch[i]); return 0; } a[i].change(j); a[w].change(k); } printf("No"); return 0; }跑得慢了点但能过就对了
- 1
信息
- ID
- 1443
- 时间
- 1000ms
- 内存
- 125MiB
- 难度
- 5
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者