1.[NOIP2005]过河
有些距离过大时,是可以直接去掉的,因为中间可以通过反复横跳来水距离,所以一旦发现距离过大,可以直接减少。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll l;
ll s,t,m;
ll mas[110];
ll dp[5000100];
ll dist[5000100];
ll dis;
bool di[5000100]={0};
int main()
{ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
cin>>l;
cin>>s>>t>>m;
for(int i=1;i<=m;++i){
cin>>mas[i];
}
sort(mas+1,mas+1+m);
if(s==t){
ll cnt=0;
for(int i=1;i<=m;++i){
if(mas[i]%t==0)
cnt++;
}
cout<<cnt<<endl;
return 0;
}
// for(int i = 1; i <= m; i++) {
// dist[i] = (mas[i] - mas[i - 1]) % 2520; // 缩点
// }
for(int i = 1; i <= m; i++) { // 缩点
dis=(mas[i] - mas[i - 1]) % 2520;
mas[i] = mas[i - 1] + dis;
di[mas[i]] = 1; // 此处有石头
}
l = mas[m]+s*t;
//l=mas[m];
/// 将l变成最后一个石头的位置+s*t
/// 如果l-b[m]>=s*t就缩成s*t
/// 如果l-b[m]<=s*t就加上一个数使得它等于这个距离因为青蛙可能跳出独木桥
memset(dp,0x3f,sizeof dp);
dp[0]=0;
for(int i = 1; i <= l; i++) {
for(int j = s; j <= t; j++) {
if(i>=j)
dp[i] = min(dp[i], dp[i - j]);
}
dp[i]+=di[i];
}
ll ans=1e12+10;
for(int i=mas[m];i<=l;++i){
ans=min(ans,dp[i]);
}
cout<<ans<<endl;
return 0;
}
2.简单瞎搞题:
思路不难想,就是用二维bool,但是bool会爆内存,所以这里用bitset来优化
dpij表示在i的层下j这个值是不是可以造出来.
#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll n;
ll l,r;
bitset<1001000> f[110];
int main()
{
cin>>n;
f[0][0]=1;
for(int i=1;i<=n;++i){
cin>>l>>r;
for(int k=l;k<=r;++k){
f[i]|=(f[i-1]<<(k*k));
}
}
cout<<f[n].count()<<endl;
return 0;
}
以后再补