NO.1 飞机降落
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
struct Plane{
int start, standing, landing;
};
int n;
Plane *plane;
bool *st;
string dfs(int x, int time)
{
if(x > n) return "YES";
for(int i = 1; i <= n; i++){
if(st[i]) continue;//如果当前位置已经考虑就跳过
if(time > plane[i].start + plane[i].standing) continue;//如果当前飞机最晚可降落时间小于当前时间就直接跳过
st[i] = true;
if(dfs(x + 1, max(plane[i].start, time) + plane[i].landing) == "YES") return "YES";
st[i] = false;
}
return "NO";
}
int main(void)
{
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
int T; cin >> T;
while(T--){
cin >> n;
plane = new Plane[n + 10];
st = new bool[n + 10];
memset(st, false, sizeof(st));
for(int i = 1; i <= n; i++) cin >> plane[i].start >> plane[i].standing >> plane[i].landing;
cout << dfs(1, 0) << endl;
}
return 0;
}
NO.2 接龙序列
暴力dfs:
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int n;
int *a;
int ans = -1;
int get_last(int x){
return x % 10;
}
int get_first(int x){
while(x > 10) x /= 10;
return x;
}
void dfs(int x, int last, int cnt)//分别表示当前考虑到了第几个数,当前最后一位数字是什么,当前序列已经有几个数
{
if(x > n){
ans = max(ans, cnt);
return;
}
if(last == -1) dfs(x + 1, get_last(a[x]), cnt + 1);//如果遇到的是第一个数字,直接记录进去
if(last == get_first(a[x])) dfs(x + 1, get_last(a[x]), cnt + 1);//如果当前数字可以记录进去就直接递归
else dfs(x + 1, last, cnt);//否则不进行记录
}
int main(void)
{
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
cin >> n;
a = new int[n + 10];
for(int i = 1; i <= n; i++) cin >> a[i];
for(int i = 1; i <= n; i++){
if(ans > n - i) break;//如果当前答案已经大于剩下未考虑的,直接跳出
dfs(i, -1, 0);//从当前位置寻找最长的接龙序列
}
cout << n - ans << endl;
return 0;
}
优化dp:
#include<iostream>
#include<cstring>
#include<algorithm>
#define int long long
using namespace std;
int dp[15] = {0};
signed main(void)
{
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
int n; cin >> n;
for(int i = 1; i <= n; i++){
string a; cin >> a;
int first = a[0] - '0', final = a[a.size() - 1] - '0';
dp[final] = max(dp[first] + 1, dp[final]);
//在选和不选之间做抉择
}
int ans = 0;
for(int i = 0; i <= 9; i++) ans = max(ans, dp[i]);
cout << n - ans << endl;
return 0;
}
NO.3:子串简写
暴力代码:
#include<iostream>
#include<cstring>
#include<algorithm>
#define int long long
using namespace std;
signed main(void)
{
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
int ans = 0;
int k; cin >> k;
string s; cin >> s;
char a, b; cin >> a >> b;
int len = s.size();
for(int i = 0; i < len - k + 1; i++){
if(s[i] == a){
for(int j = i + k - 1; j < len; j++){
if(s[j] == b) ans++;
}
}
}
cout << ans << endl;
return 0;
}
记忆化优化:
#include<iostream>
#include<cstring>
#include<algorithm>
#define int long long
using namespace std;
int *mem_a;
signed main(void)
{
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
int k; cin >> k;
string s; cin >> s;
char a, b; cin >> a >> b;
int len = s.size();
mem_a = new int[len + 10];
memset(mem_a, 0, sizeof(mem_a));
for(int i = 0; i < len - k + 1; i++){
if(i >= 1) mem_a[i] = mem_a[i - 1];
if(s[i] == a){
mem_a[i]++;
}
}
int ans = 0;
for(int i = k - 1; i < len; i++){
if(s[i] == b) ans += mem_a[i - k + 1];
}
cout << ans << endl;
return 0;
}
NO.4:买瓜
dfs + 剪枝优化
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int n, m;
int *a;
int *sum;
int ans = 0x3f3f3f3f;
bool flag = 0;
void dfs(int x, double wei, int cnt)
{
if(wei == (double)m){
ans = min(ans, cnt);
return;//如果当前重量符合要求,记录当前答案
}
if(cnt >= ans) return;//如果当前的刀数已经大于合法方案的刀数直接返回
if(sum[x] + wei < m) return;//因为所有瓜的重量都是从大到小选,因此当后面的西瓜所有重量都小于剩下要选的重量时候,直接剪枝返回即可
if(wei > (double)m) return;//如果当前买的瓜重量大于需要的重量,直接返回
if(x > n) return;//如果当前瓜都考虑完,直接返回
//选整个瓜
dfs(x + 1, wei + a[x], cnt);
//选半个瓜
dfs(x + 1, wei + a[x] / 2.0, cnt + 1);
//不选
dfs(x + 1, wei, cnt);
}
int main(void)
{
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
cin >> n >> m;
a = new int[n + 10];
sum = new int[n + 10];
for(int i = 1; i <= n; i++) cin >> a[i];
sort(a + 1, a + n + 1);
sum[n] = a[n];
for(int i = n - 1; i >= 1; i--) sum[i] = sum[i + 1] + a[i];
dfs(1, 0, 0);
if(ans == 0x3f3f3f3f){
cout << -1 << endl;
return 0;
}
cout << ans << endl;
return 0;
}