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;
}