暴力第7章(未完善)

A

暴力跑 模拟分母

#include<bits/stdc++.h>
#include<iostream>
#include<cstring>
#include<queue>
#define inf 0x3f3f3f3f
//2147483647
using namespace std;
typedef long long ll;

typedef pair<double, double> PII;
ll n,m,k;
ll cnt=0,sum=0;
ll ans=0;
ll mod=1e9+7;
const int maxn=1e6+199;
ll x,y;char a[100];

int main(){
	
	while(cin>>n){
		if(n==0) break; 
		int c=1233;
		int flag=0;
		while(c++){
			int b=c*n;
			sprintf(a,"%05d%05d",b,c);
			if(strlen(a)>10)
			break;
			int pre[200];
			memset(pre,0,sizeof(pre));
			int i=0;
			for(i=0;i<10;i++){
				if(pre[a[i]-'0']) break;
				
				pre[a[i]-'0']++;
			}
			if(i==10)
			{	
				printf("%05d / %05d = %lld\n",b,c,n);
				flag=1;
				}
		}
		if(!flag){
			printf("There are no solutions for %d.\n",n);
		}
		putchar('\n');
	}
	return 0;
}

B

找连续子序列最大乘机
两个for模拟即可

#include<bits/stdc++.h>
#include<iostream>
#include<cstring>
#include<queue>
#define inf 0x3f3f3f3f
//2147483647
using namespace std;
typedef long long ll;

typedef pair<double, double> PII;
ll n,m,k;
ll cnt=0,sum=0;
ll ans=0;
ll mod=1e9+7;
const int maxn=1e6+199;
ll x,y;ll a[maxn];
ll gcd(int x,int y){
	if(x%y==0)
	return y;
	
	return gcd(y,x%y);
}
int main(){
	
	while(cin>>n){
		for(int i=1;i<=n;i++) cin>>a[i];
		
		ll maxl=0;
		
		for(int i=1;i<=n;i++){
			ll sum=1;
			for(int j=i;j<=n;j++){
				sum*=a[j];
				maxl=max(maxl,sum);
			}
			
			
		}
		cout<<"Case #"<<++cnt<<": The maximum product is "<<maxl<<"."<<endl;
		cout<<endl;
	}
	return 0;
}

C

当两个分数一样是 到达一个临界点
然后 一个变大 一个变小

我们只需要枚举变大的那一个
所以只需要从2*n 枚举到n+1即可

#include<bits/stdc++.h>
#include<iostream>
#include<cstring>
#include<queue>
#define inf 0x3f3f3f3f
//2147483647
using namespace std;
typedef long long ll;

typedef pair<double, double> PII;
ll n,m,k;
ll cnt=0,sum=0;
ll ans=0;
ll mod=1e9+7;
const int maxn=1e6+199;
ll x,y;char a[100];
ll gcd(int x,int y){
	if(x%y==0)
	return y;
	
	return gcd(y,x%y);
}
int main(){
	map<int,int>mp;
	int n;
	while(cin>>n){
		
		mp.clear();
		cnt=0;
		for(int i=n*2;i>n;i--){
			if(n*i%(i-n)==0)
			cnt++;
			
		}
		cout<<cnt<<endl;
		for(int i=n+1;i<=2*n;i++){
			if(n*i%(i-n)==0)
			printf("1/%d = 1/%d + 1/%d\n",n,n*i/(i-n),i);
		}
		
	}
	return 0;
}

D

素数环 相邻两个数的和是素数

采取回溯法写即可 在新位置上填数 然后判断进行下一步
然后写一个终止条件

#include<bits/stdc++.h>
#include<iostream>
#include<cstring>
#include<queue>
#define inf 0x3f3f3f3f
//2147483647
using namespace std;
typedef long long ll;

typedef pair<double, double> PII;
ll n,m,k;
ll cnt=0,sum=0;
ll ans=0;
ll mod=1e9+7;
const int maxn=1e6+199;
ll x,y;	
int pre[200];
int bj[200];
int a[100];
int vis[200];
ll smp(){
	for(int i=2;i<=100;i++){
		if(!bj[i])
		pre[cnt++]=i;
		
		for(int j=0;j<cnt&&pre[j]*i<=200;j++){
			bj[pre[j]*i]=1;
			if(i%pre[j]==0) break;
		}
	}
}
void dfs(int tot){
	if(tot==n&&!bj[a[0]+a[n-1]]){
		cout<<a[0];
		for(int i=1;i<n;i++) cout<<" "<<a[i];
		cout<<endl;
	}
	else{
		for(int i=2;i<=n;i++){
			if(!bj[i+a[tot-1]]&&!vis[i])
			{
				a[tot]=i;
				vis[i]=1;
				dfs(tot+1);
				vis[i]=0;
			}
		}
	}
}
int main(){
	
	smp();
	while(cin>>n){
	a[0]=1;
	cout<<"Case "<<++ans<<":"<<endl;
	dfs(1);
	putchar('\n');
	}
	return 0;
}

E

令当前游标为tot,假设cur以前的字符串是困难的串(dfs已经判断过),那么只用考虑当前插入tot处的字符和之前的串是否满足困难串的条件;这样就是以tot为基准点依次向前对称匹配,从一个字符到(tot+1)/2个字符的匹配。

#include<bits/stdc++.h>
#include<iostream>
#include<cstring>
#include<queue>
#define inf 0x3f3f3f3f
//2147483647
using namespace std;
typedef long long ll;
typedef pair<double, double> PII;
ll n,m,k;
ll cnt=0,sum=0;
ll mod=1e9+7;
const int maxn=1e6+199;
ll l,r;	
map<int,int>mp;
priority_queue<int , vector<int>,greater<int> >q;bool number[maxn];
int h=0;
ll s[maxn];
void print(int tot){
	int i;
	 for(i=0;i<tot;i++)
        {
            if(i!=0&&i%4==0) 
                if(i!=0&&i%64==0)
                    printf("\n");
                else
                    printf(" ");
            printf("%c",'A'+s[i]);
        }
        printf("\n%d\n",tot);
}

int dfs(int tot){
	if(cnt++==n) {
		print(tot);
		return 0;
	}
	
	for(int i=0;i<m;i++){  //将第tot位进行填补
		s[tot]=i;
		
		int ok=1;
		for(int j=1;j<=(tot+1)/2;j++){  //判断是否有重复子串
			int flag=1;
			for(int len=0;len<j;len++){
				if(s[tot-len]!=s[tot-j-len]) {
					flag=0;
					break;
				}
			}
			if(flag){
				ok=0;
				break;
			}
		}
		if(ok){
			if(!dfs(tot+1)) return 0;
		}
	}
	return 1;
}
int main(){
	
	while(cin>>n>>m&&n&&m){
		memset(s,0,sizeof(s));
		cnt=0;
		dfs(0);
		
	}
	return 0; 
}

F

这是一个图,输入给出的是某个节点。冒号后面的是和这个节点相邻的节点有哪些 分号代表一个描述结束;
每一种排法中,相邻点距离最大的,作为这种排法的带宽。 问哪种排法带宽最小;
求最小宽度 用全排列即可

#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
const int maxn=2e5+100;
vector<int> v[26];
bool ch[26]; 
int ans[10],id[10];


int main(){
	string line;
	while(cin>>line && line[0]!='#'){
		for(int i=0;i<26;i++) v[i].clear();
		memset(ch,0,sizeof(ch));
		for(int i=0,j,len=line.length();i<len;i++){
			ch[line[i]-'A']=true;
			for(j=i+2;j<len && line[j]!=';';j++){
				v[line[i]-'A'].push_back(line[j]-'A');
				ch[line[j]-'A']=true;
			}
			i=j;
		}

	int n=0;
		for(int i=0;i<26;i++) if(ch[i]) id[n++]=i;
		int res=n;
		do{
			int maxn=0;
			for(int i=0;i<n;i++){
				for(int j=0,len=v[id[i]].size();j<len;j++){
					for(int k=0;k<n;k++){
						if(id[k]==v[id[i]][j]) {
							maxn=max(maxn,abs(k-i));							
							break;
						}
					}
					if(maxn>=res) break;
				}
				if(maxn>=res) break;
			}
			if(res>maxn){
				memcpy(ans,id,sizeof(id));
				res=maxn;
			}
		}while(next_permutation(id,id+n));
		for(int i=0;i<n;i++)
			cout<<char(ans[i]+'A')<<" ";					
		cout<<"-> "<<res<<endl;
	}
	return 0;
}

J

迭代加深法
题目大意:将一个数字序列以最少的剪切次数粘贴成另一个数字序列。
剪枝策略判断:当前估价函数值+当前深度>预先最大搜索深度 然后剪枝
剪枝最多改变三个数字位置的正确性
每次搜索前h>(maxd-d)*3时剪枝 (maxd-d)是剩余搜索次数

/*

*/
#include<bitsdc++.h> 
using namespace std;
const int maxn = 9;
int n, a[maxn];
bool is_finish() {
  for(int i = 0; i < n-1; i++)
    if(a[i] >= a[i+1]) return false;
  return true;
}// 判断是否到达目标状态
int h() {
  int cnt = 0;
  for(int i = 0; i <n-1; i++)
    if(a[i]+1 != a[i+1]) cnt++;
  if(a[n-1] != n) cnt++;
  return cnt;
} //统计需要变更的总数
bool dfs(int d, int maxd) {
  if(d*3 + h() > maxd*3) return false; //估价函数
  if(is_finish()) return true; //边界条件 
 
  int b[maxn], former[maxn];
  memcpy(former, a, sizeof(a)); //存放原图
  for(int i = 0; i < n; i++)
   for(int j = i; j < n; j++) {
     int cnt = 0;
     for(int k = 0; k < n; k++)
       if(k < i || k > j) b[cnt++] = a[k];
     for(int k = 0; k <= cnt; k++) {
       int cnt2 = 0;
       for(int p = 0; p < k; p++) a[cnt2++] = b[p]; //插入已经拍好序的
       for(int p = i; p <= j; p++) a[cnt2++] = former[p]; //插入
       for(int p = k; p < cnt; p++) a[cnt2++] = b[p]; //插入终止状态
 
       if(dfs(d+1, maxd)) return true;
       memcpy(a,former, sizeof(a));
     }
   }
  return false;
}
int solve() {
  if(is_finish()) return 0;
  int ans = 8;
  for(int maxd = 1; maxd <ans; maxd++)
    if(dfs(0, maxd)) return maxd;
  return ans;
}
int main() {
  int kass= 0;
  while(cin>>n&&n) {
    for(int i = 0; i < n; i++) scanf("%d", &a[i]);
    printf("Case %d: %d\n", ++kass, solve());
  }
  return 0;
}

H

T组测试数据,每组测试数据输入4个整数,分别表示第一个杯子的容量、第二个杯子的容量、第三个杯子的量、目标容量,4个整数(小于200大于0)。输出最小的总倒水量和目标容量,如果倒不出目标容量,就 输出能倒出的小于目标容量的最大的容量的总倒水量和容量。
a->b a->c b->a b->c c->a c->b 有这几种情况
桶是没有刻度的 只有容量大小

我们优先提取出 倒水过程中用量最少的 因为这样是最优的

#include<bits/stdc++.h>
#include<iostream>
#include<cstring>
#include<queue>
#define inf 0x3f3f3f3f
//2147483647
using namespace std;
typedef long long ll;

typedef pair<double, double> PII;
ll n,m,k;
ll cnt=0,sum=0;
ll mod=1e9+7;
const int maxn=1e6+199;
ll x,y;	
int cap[3];
int vis[250][250];
int ans[250];

struct Node{
	int v[3];
	int dis;
	bool operator <(const Node& res) const{
		return res.dis<dis;
	}
}f,t;
void __init__(const Node & u){
	for(int i=0;i<3;i++){
		int k=u.v[i];
		if(ans[k]<0||ans[k]>u.dis) ans[k]=u.dis;
	}
}
void bfs(int a,int b,int c,int d){
	memset(vis,0,sizeof(vis));
	memset(cap,0,sizeof(cap));
	memset(ans,-1,sizeof(ans));
	cap[0]=a;cap[1]=b;cap[2]=c; //桶的容量
	priority_queue<Node>q;
	f.v[0]=0;
	f.v[1]=0;
	f.v[2]=c;
	f.dis=0;
	vis[0][0]=1;
	q.push(f);
	
	while(q.size()){
		f=q.top();   //提取出dis最小的  dis代表 倒水使用量
		q.pop();
		__init__(f);
		if(ans[d]>=0) break; //如果这个水量已经达到 直接break;
		
		for(int i=0;i<3;i++){
			for(int j=0;j<3;j++){
				if(i==j) continue;
				if(f.v[i]==0||f.v[j]==cap[j]) continue;
				
				int tmp=min(cap[j],f.v[i]+f.v[j])-f.v[j];  //tmp 代表j桶可以接收多少体积
				t=f;
				t.v[i]=f.v[i]-tmp;
				t.v[j]=f.v[j]+tmp;
				t.dis=f.dis+tmp;
				if(!vis[t.v[0]][t.v[1]]) //如果这个状态未曾有过 入队
				{
					vis[t.v[0]][t.v[1]]=1;
					q.push(t);
					
				}
			}
		}
	}
	
	while(d>=0){
		if(ans[d]>=0) {
				
				printf("%d %d\n",ans[d],d);
				return;
			}	
		
		d--;
	}
	
}

int main(){
	cin>>n;
	while(n--){
		int a,b,c,d;
		cin>>a>>b>>c>>d;
		bfs(a,b,c,d);
	}
}

K

两个宝石 体积价值分别为 s1 v1 、s2 v2
给我们一个背包容量 宝石数量无限
如何取得最大价值

可能会是背包 但是数据太大
如果背包容量不是很大的话 比如 n/s1 <1e6 我们可以边跑边判断取得最大价值

如果容量太大 T了 就要换一种思路 如果拿s2件v1 他的价值就是s2v1 体积是s2v1

同样的拿s1件v2 他的价值为 s1v2 体积是s1s2
我们可以看到 他们的体积一样 都是s1s2 然后我么可以比较他们的价值
如果s2v1更大的话 说明 每一个s2v1体积 我都可以装v1这个宝石 因为这个体积下 v1的价值更大

然后不足s1s2的体积 我们可以暴力跑 判断装v2是否有最大价值

#include<bits/stdc++.h>
#include<iostream>
#include<cstring>
#include<queue>
#define inf 0x3f3f3f3f
//2147483647
using namespace std;
typedef long long ll;

typedef pair<double, double> PII;
ll n,m,k;
ll cnt=0,sum=0;
ll mod=1e9+7;
const int maxn=1e6+199;
ll x,y;	

int main()
{
	cin>>m;
	while(m--){
		
		ll s1,v1,s2,v2;
		cin>>n>>s1>>v1>>s2>>v2;
		ll maxl=-1;
		if(n/s1<1e6){
			for(ll i=0;i<=n/s1;i++){
				sum=i*v1;
				sum+=(n-i*s1)/s2*v2;
				maxl=max(sum,maxl);
			}
		}else if(n/s2<1e6){
			for(ll i=0;i<=n/s2;i++){
				sum=i*v2;
				sum+=(n-i*s2)/s1*v1;
				maxl=max(sum,maxl);
			}
		}else{
			if(s2*v1<s1*v2){
				for(ll i=0;i<=s2;i++){
					sum=i*v1;
					sum+=(n-i*s1)/s2*v2;
					maxl=max(sum,maxl);
				}
			}else{
				for(ll i=0;i<=s1;i++){
					sum=i*v2;
					sum+=(n-i*s2)/s1*v1;
					maxl=max(sum,maxl);
				}
			}
		}
		cout<<"Case #"<<++cnt<<": ";
		cout<<maxl<<endl;
	}
    return 0;
}

L

也是一个小小的dfs啊 可以利用计算后的结果 只能进行乘除运算
对于幂来说就是加减运算

我们把每一次计算的结果保存下来
然后然后然后利用就好

#include<bits/stdc++.h>
#include<iostream>
#include<cstring>
#include<queue>
#define inf 0x3f3f3f3f
//2147483647
using namespace std;
typedef long long ll;

typedef pair<double, double> PII;
ll n,m,k;
ll cnt=0,sum=0;
ll mod=1e9+7;
const int maxn=1e6+199;
ll l,r;	
map<int,int>mp;
priority_queue<int , vector<int>,greater<int> >q;
bool number[maxn];
ll prime[maxn];
int h=0;
int a[maxn];

bool dfs(int x,int d){
	if(d>h) return 0;
	if(x==n) return 1;
	if(x<<(h-d)<n) return 0;
	a[d]=x;
	for(int i=0;i<=d;i++){
		if(dfs(a[i]+x,d+1)) return 1;
		if(dfs(abs(a[i]-x),d+1)) return 1;
	}
	return 0;
	
}
int main(){
	
	while(cin>>n&&n){
		h=0;
		
		while(!dfs(1,0)) h++;
		
		cout<<h<<endl;
		
	}
	return 0; 
}
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 9
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

牛郎恋刘娘,刘娘念牛郎

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值