7.13暑假集训

 感觉昨天也没做多少题目...在做题的时候一直在想着电视剧...原谅我是个深情的人...

昨天做的几道题目,感觉都不太会....我还是太菜了

今天晚上还有小白月赛,加油吧

P1433 吃奶酪

这题如果暴力dfs的化,复杂度为15!,会超时,所以需要减枝

这题正确解法是状压dp。

但这题也可以状压+搜索

我们设dp[i][j],i为当前状态(用二进制表示),j表示当前在那个点

如果dp[i]][j]!=0&&dp[i][j]<=s+dis(j,now)(j为当前点,now为前点)就return

否则dp[i][j]=s+dis(j,now),感觉就是个记忆化搜索

#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
#include<stack>
#include<deque>
#include<vector>
#include<map>
#include<set>
#include <utility>
#include <list>
using namespace std;
typedef  long  long ll ;
#define pii pair<int,int>
const int inf = 0x3f3f3f3f;//106110956
inline int read(){
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9'){
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9'){
        x = (x<<1) + (x<<3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}
void print(__int128 num) {
	if(num) {
		print(num/10);
		putchar(num%10+'0');
	}
}
ll ex_gcd(ll a,ll b,ll& x,ll& y){
	if(b==0){
		x=1;
		y=0;
		return a;
	}

	ll d=ex_gcd(b,a%b,y,x);
	y=y-a/b*x;
	return d;
}
double 	a[20],b[20];
double ans=1e9;
double dist(int x,int y){
	 sqrt((a[x]-a[y])*(a[x]-a[y])+(b[x]-b[y])*(b[x]-b[y]));
}
int n;
double dp[65000][20];
int vis[20];
void dfs(int dep,double s,int now,int b){
	if(s>ans)return ;
	
	if(dep==n+1){
		ans=ans<s?ans:s;
		return;
	}
	
	for(int i=1;i<=n;i++){
		if(vis[i]==0){
		int p=b+(1<<(i-1));
		if(dp[p][i]!=0&&dp[p][i]<=s+dist(i,now))continue;
		vis[i]=1;
		dp[p][i]=s+dist(i,now);
		dfs(dep+1,dp[p][i],i,p);
		vis[i]=0;
		}
	}
}
int main(){
	
	 
	scanf("%d",&n);
	
	for(int i=1;i<=n;i++){
		scanf("%lf%lf",&a[i],&b[i]);
	}
	
	
	dfs(1,0,0,0);
	
	printf("%.2lf\n",ans);
	
	return 0;
	
}

P1605 迷宫

一道非常简单的求路径数目的题...

我还不太会..我是真滴菜..

一般来说bfs来求最短路,dfs+回溯求方案数然后就是模板题了

#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
#include<stack>
#include<deque>
#include<vector>
#include<map>
#include<set>
#include <utility>
#include <list>
using namespace std;
typedef  long  long ll ;
#define pii pair<int,int>
const int inf = 0x3f3f3f3f;//106110956
inline int read(){
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9'){
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9'){
        x = (x<<1) + (x<<3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}
void print(__int128 num) {
	if(num) {
		print(num/10);
		putchar(num%10+'0');
	}
}
ll ex_gcd(ll a,ll b,ll& x,ll& y){
	if(b==0){
		x=1;
		y=0;
		return a;
	}

	ll d=ex_gcd(b,a%b,y,x);
	y=y-a/b*x;
	return d;
}

int dx[]={0,0,-1,1};
int dy[]={1,-1,0,0};
int vis[100][100];
int mp[100][100];
int n,m,t;
int sx,sy,fx,fy;
ll ans=0;

void dfs(int x,int y){
	if(x==fx&&y==fy){
		ans++;
		return ;
	}
	
	for(int i=0;i<=3;i++){
		int nx=x+dx[i];
		int ny=y+dy[i];
		if(nx>=1&&ny>=1&&nx<=n&&ny<=m&&vis[nx][ny]==0){
			vis[x][y]=1;
			dfs(nx,ny);
			vis[x][y]=0;
		}
	}
	
	
}

int main(){
	
	cin>>n>>m>>t;
	cin>>sx>>sy>>fx>>fy;
	int x,y;
	for(int i=1;i<=t;i++){
		cin>>x>>y;
		vis[x][y]=1;
		
	}
	
	vis[sx][sy]=1;
	dfs(sx,sy);
	
	printf("%lld\n",ans);
	
	return 0;
}

P1162 填涂颜色

这题一开始我做的巨麻烦,还没整出来....太菜了啊= =

我想到了只要一个连通块有在边界处的,就不满足条件,否则就满足条件

然后我遍历整个数组,只要有0就开搜,搜完后,并打标价,搜完后,如果没搜到边界就在遍历整个数组,把标记的赋值为2,否则标记不变

然后改了好久都没整出来....我太菜了= =

我的想法是正确的,但没变要这么麻烦,我们只需从边界0开始搜素即可,

如果搜到了就标记。

最后没有标记的0我们就赋值为2即可

#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
#include<stack>
#include<deque>
#include<vector>
#include<map>
#include<set>
#include <utility>
#include <list>
using namespace std;
typedef  long  long ll ;
#define pii pair<int,int>
const int inf = 0x3f3f3f3f;//106110956
inline int read(){
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9'){
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9'){
        x = (x<<1) + (x<<3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}
void print(__int128 num) {
	if(num) {
		print(num/10);
		putchar(num%10+'0');
	}
}
ll ex_gcd(ll a,ll b,ll& x,ll& y){
	if(b==0){
		x=1;
		y=0;
		return a;
	}

	ll d=ex_gcd(b,a%b,y,x);
	y=y-a/b*x;
	return d;
}
int n;
int vis[40][40];
int dx[]={0,0,-1,1};
int dy[]={-1,1,0,0};
struct Node{
	int x,y;
};
void bfs(int x,int y){
	queue<Node>q;
	q.push({x,y});
	while(!q.empty()){
		Node u=q.front();
		q.pop();
		for(int i=0;i<=3;i++){
			int nx=u.x+dx[i];
			int ny=u.y+dy[i];
			if(nx>=1&&nx<=n&&ny>=1&&ny<=n&&vis[nx][ny]==0){
					vis[nx][ny]=3;
					q.push({nx,ny});
			}
		}
	}
}
int main(){
	cin>>n;
	
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			cin>>vis[i][j];
		}
	}
	for(int i=2;i<=n-1;i++){
		if(vis[i][1]==0){
			vis[i][1]=3;
			bfs(i,1);
		}
		if(vis[i][n]==0){
			vis[i][n]=3;
			bfs(i,n);
		}
	}	
	
	for(int i=1;i<=n;i++){
		if(vis[1][i]==0){
			vis[1][i]=3;
			bfs(1,i);
		}
		
		if(vis[n][i]==0){
			vis[n][i]=3;
			bfs(n,i);
		}
	}
	for(int i =1;i<=n;i++){
		for(int j=1;j<=n;j++){
			if(vis[i][j]==3){
				printf("0 ");
			}
			if(vis[i][j]==0){
				printf("2 ");
			}
			if(vis[i][j]==1){
				printf("1 ");
			}
			
		}
		printf("\n");
	}
	

	return 0;
}

P1825 [USACO11OPEN] Corn Maze S

做了一天搜素,这题是晚上做的,感觉思路好混乱...不知道咋做...bfs还是dfs,表不标记,回不回溯..

这题是求最短路,所以用bfs,为了防止重复搜素,我们打标记,不用回溯

然后就是个简单题目了...

#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
#include<stack>
#include<deque>
#include<vector>
#include<map>
#include<set>
#include <utility>
#include <list>
using namespace std;
typedef  long  long ll ;
#define pii pair<int,int>
const int inf = 0x3f3f3f3f;//106110956
inline int read(){
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9'){
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9'){
        x = (x<<1) + (x<<3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}
void print(__int128 num) {
	if(num) {
		print(num/10);
		putchar(num%10+'0');
	}
}
ll ex_gcd(ll a,ll b,ll& x,ll& y){
	if(b==0){
		x=1;
		y=0;
		return a;
	}

	ll d=ex_gcd(b,a%b,y,x);
	y=y-a/b*x;
	return d;
}
char a[305][305];
int n,m;
int sx,sy,fx,fy;
struct Node{
	int x,y,step;
};
int x2,y2;
int dx[]={0,0,-1,1};
int dy[]={1,-1,0,0};
void find(int x,int y){
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			if(a[i][j]==a[x][y]&&(i!=x||j!=y)){
				x2=i;
				y2=j;
				return ;
			}
		}
	}
}
int vis[305][305];
int bfs(){
	queue<Node>q;
	q.push({sx,sy,0});
	while(!q.empty()){
		Node u=q.front();
		q.pop();
		
		for(int i=0;i<4;i++){
			int nx=u.x+dx[i];
			int ny=u.y+dy[i];
			if(nx<=0||nx>n||ny<=0||ny>m||a[nx][ny]=='@')continue;
			if(a[nx][ny]=='#')continue;
			if(vis[nx][ny])continue;
			vis[nx][ny]=1;
			if(a[nx][ny]=='.'){
				q.push({nx,ny,u.step+1});
			}
			if(nx==fx&&ny==fy){
				return u.step+1;
			}
			if('A'<=a[nx][ny]&&a[nx][ny]<='Z'){
				find(nx,ny); 
				q.push({x2,y2,u.step+1});
			}
		}                  			
	}
}
int main(){
	
	cin>>n>>m;
	
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			cin>>a[i][j];
			
			if(a[i][j]=='='){
				fx=i;
				fy=j;
			}
			
			if(a[i][j]=='@'){
				sx=i;
				sy=j;
			}
		}
	}	
	
	cout<<bfs();
	return 0;
}

P1106 删数问题

感觉这题好难啊..

自己写的麻烦死...改了快2个小时才改好的...

比较正确的思路:

样例175438 

我们发现1比7小所以不删,7比5大所以删,5比4大所以删,4比3大删除,3比8小不删,8比0大删除

如果一个数比后面大就删除,否则就不删

下面是删除的方法注意第二层循环中,有break,因为只要搜到,并赋值后,防止后面在赋值!!

break很关键

	for(int i=1;i<=K;i++){//删除 
		for(int j=1;j<=n;j++){//长度 
			if(a[j]>a[j+1]){
				for(int k=j;k<n;k++){
					a[k]=a[k+1];	
				}
				n--;
				break;
			} 
			
		}
	}
	

输出我们开始时赋值now为n

i小于等于min(n,now-K)的最小值,防止出现12345678这种单调的序列

还有0的输出!

for(int i=1;i<=min(now-K,n);i++){
		if(a[i]!=0){
			flag=1;
			cout<<a[i];
		}else{
			if(flag){
				cout<<"0";
			}
		}
	}

我的做法就异常的麻烦了...

我用的是差分

因为删除的数为4

我发现175438开始时候,从1遍历到第5个位置,然后求里面最小数的位置,然后删除最小数前面的所有数(差分)

注意0是可以当开头的

但是我当时样例一直过不了,一直输出138...

因为我差分的位置为上一个pos点和这个pos点,如果 出现38并且上次pos点和这次pos点重复,的情况,8这个位置就没进行差分操作

now为现在的次数,如果now==n-pos,说明后面的数都需要删除

if(now==n-pos){
			d[pos+1]++;
			break;
		}
#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
#include<stack>
#include<deque>
#include<vector>
#include<map>
#include<set>
#include <utility>
#include <list>
using namespace std;
typedef  long  long ll ;
#define pii pair<int,int>
const int inf = 0x3f3f3f3f;//106110956
inline int read(){
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9'){
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9'){
        x = (x<<1) + (x<<3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}
void print(__int128 num) {
	if(num) {
		print(num/10);
		putchar(num%10+'0');
	}
}
ll ex_gcd(ll a,ll b,ll& x,ll& y){
	if(b==0){
		x=1;
		y=0;
		return a;
	}

	ll d=ex_gcd(b,a%b,y,x);
	y=y-a/b*x;
	return d;
}
int k;
string s;
int d[300];
int main(){
	cin>>s;
	cin>>k;
	int n=s.length();
	
	s=" "+s;
	
	int pos=0;
	
	int num;
	int now=k;
	
	while(1){
				
		num=10;
		
		int pos1=pos+1;
		if(now==n-pos){
			d[pos+1]++;
			break;
		}
		
		for(int j=pos1;j<=min(n,pos1+now);j++){
				if((s[j]-'0')<num){
					num=s[j]-'0';
					pos=j;
				}		
			}
		
		now=now-(pos-pos1);			
		d[pos1]++;
		d[pos]--;	
						
	}
	
	
	int sum=0;
	int flag=0;
	for(int i=1;i<=n;i++){
		sum=sum+d[i];
		if(sum==0){
			if(s[i]!='0'){
				flag=1;
				cout<<s[i];
			}else{
				if(flag){
				cout<<"0";
				}else{
					continue;
				}
			}
		}else{
			continue;
		}
	}
	if(flag==0){
		cout<<"0";
	}
	
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值