10月17日复盘

p1077(摆花)

题目链接


状态:dp(i,j) 表示前 i 个数总和为 j 的方案数。

答案: dp[n][m];

状态转移方程:

​
	for(int i=1;i<=n;i++){
		for(int j=0;j<=m;j++){
			for(int k=0;k<=a[i];k++){
				if(j>=k){
					dp[i][j]=(dp[i][j]%mod+dp[i-1][j-k]%mod)%mod;
				}
			}
		}
	}

​

初始状态:dp[0][0]=1;

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=1e3+33,mod=1e6+7;
int a[N];
int dp[N][N];
int n,m;
int main(){
	dp[0][0]=1;
	cin >> n >> m;
	for(int i=1;i<=n;i++){
		cin >> a[i];
	}
	for(int i=1;i<=n;i++){
		for(int j=0;j<=m;j++){
			for(int k=0;k<=a[i];k++){
				if(j>=k){
					dp[i][j]=(dp[i][j]%mod+dp[i-1][j-k]%mod)%mod;
				}
			}
		}
	}
	cout << dp[n][m];
}

p2196(挖地雷)

题目链接


状态:dp[i]代表到达点i时的最大点权和;

答案:max(dp[i]);

状态转移:

	for(int i=1;i<=n;i++){
		for(int j=0;j<nbr[i].size();j++){
			int pre=nbr[i][j];
			if(dp[i]<dp[pre]+a[i]){
				dp[i]=dp[pre]+a[i];
				last[i]=pre;
			}
		}
	}

初始状态:

dp[i]=a[i]

输出路径:

dfs,栈.....

void dfs(int cur){
	if(cur == 0){
		return;
	}
	dfs(last[cur]);
	cout << cur << ' ';
}

 代码:

#include<bits/stdc++.h>
using namespace std;
const int N=1e2+333;
vector<int>nbr[N];
int dp[N],n,m,pre,res=0,ep=0,a[N],b,last[N];
void dfs(int cur){
	if(!cur){
		return;
	}
	dfs(last[cur]);
	cout << cur << ' ';
}
int main(){
	cin >> n;
	for(int i=1;i<=n;i++){
		cin >> a[i];
		dp[i]=a[i];
	}
	for(int i=1;i<=n;i++){
		for(int j=i+1;j<=n;j++){
			cin >> b; 
			if(b){
				nbr[j].push_back(i);
			}
		}
	}
	for(int i=1;i<=n;i++){
		for(int j=0;j<nbr[i].size();j++){
			pre=nbr[i][j];
			if(dp[i]<dp[pre]+a[i]){
				dp[i]=dp[pre]+a[i];
				last[i]=pre;
			}
		}
	}
	for(int i=1;i<=n;i++){
		if(res<dp[i]){
			res=dp[i];
			ep=i;
		}
	}
	dfs(ep);
	cout << endl;
	cout << res << endl;
	return 0;
}

p2066(机器分配)

题目链接


dfs和dp都可

还是写dfs吧

将它比作填格子

cur表示将要填第cur个格子

sum表示已经分配了多少个机器

val表示目前得到的总收益

当填完格子且分完机器且总收益比最大收益还大

则更新答案和最大收益

否则填完格子

return;

未填完就

继续填格子

见代码:

#include<bits/stdc++.h>
using namespace std;
const int N=1e2+88;
int n,m;
long long x,y,tmp[N],res_res[N],res=0,sum=0;
bool vis[N];
int a[N][N];
void uher(){
	for(int i=1;i<=n;i++){
		res_res[i]=tmp[i];
	}
	return;
}
void dfs(int cur,int sum,int val){
	if(cur == n+1 and sum == m){
		if(val > res){
			res=val;
			uher();
		}
		return;
	}
	if(cur==n+1){
		return;
	}
	for(int i=0;i+sum<=m;i++){
		tmp[cur]=i;
		dfs(cur+1,sum+i,val+a[cur][i]);
	}
}
int main(){
	cin >> n >> m;
	for(int i=1;i<=n;i++){
		for(int j = 1;j<=m;j++){
			cin >> a[i][j];
		}
	}
	dfs(1,0,0);
	cout << res << '\n';
	for(int i=1;i<=n;i++){
		cout << i <<' '<< res_res[i] << '\n';
	}
	return 0;
}

p8604([蓝桥杯 2013 国 C] 危险系数)

题目链接


看了看范围可以用dfs;

先用邻接矩阵存图

再dfs(x);//x为当前的起点

cur表示当前是到了那个点

如果cur == y(也就是到了终点时)

sum(路径)++;

走过的点都++;

否则:

继续往后走

最后

如果这个点被经过的次数与路径数相等

答案++;

输出答案-1

因为起点不算

若无路径

输出-1;

放代码:

#include<bits/stdc++.h>
using namespace std;
const int N=1e3+88;
int n,m;
long long x,y,cnt[N],res=0,sum=0;
bool vis[N],a[N][N];
void dfs(int cur){
	if(cur == y){
		sum++;
		for(int i=1;i<=n;i++){
			if(vis[i]){
				cnt[i]++;
			}
		}
	}else{
		for(int i=1;i<=n;i++){
			if(a[cur][i] and !vis[i]){
				vis[i]=1;
				dfs(i);
				vis[i]=0;
			}
		}
	}
}
int main(){
	cin >> n >> m;
	for(int i=1;i<=m;i++){
		cin >> x >> y;
		a[x][y] = a[y][x] = 1;
	}
	cin >> x >> y;
	dfs(x);
 	if(!sum){
 		cout << -1;
 		return 0;
 	}
	for(int i=1;i<=n;i++){
		if(cnt[i] == sum){
			res++;
		}
	}
	cout << res-1;
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值