寒假第二周题解
动态规划学习
定义:
动态规划算法就是通过差分问题,定义问题状态和状态之间的关系,使问题能够以递推的方式解决。
动态规划算法的基本思想:
将带求解问题分解为若干个子问题,按顺序求解子问题,前子问题的解,为后一子问题的求解提供了有用的信息。在求解任意子问题时,列出各种可能的局部解,通过决策保留那些有可能达到最优的局部解,丢弃其他局部解。依次解决各子问题,最后一个子问题就是初始问题的解。
思考:
如果只有一种情况,最佳的选择是什么,然后根据这个最佳选择往前进一步推导,得到前一步的最佳。然后就是定义问题状态和状态之间的关系。类似于推导公式,推导步骤之间的关系(用程序语言来编写),也就是状态转移方程。
例题
1、CodeForces 1466B
#include <iostream>
using namespace std;
int n;
int a[200001];
int b[200001];
int main()
{
int t ;
cin >> t;
while(t--)
{
cin >> n;
for(int i=0;i<=2*n+3;i++)
{
b[i]=0;
}
for(int i=1;i<=n;i++)
cin >> a[i];
for(int i=n;i>=1;i--)
{
if(i==n||a[i]+1<a[i+1])
a[i]++;
}
for(int i=1;i<=n;i++)
{
b[a[i]]=1;
}
int ans=0;
for(int i=1;i<=2*n+2;i++)
{
if(b[i])
{
ans++;
}
}
cout << ans << endl;
}
return 0;
}
2、CodeForces 1462B
#include <iostream>
using namespace std;
string str;
int n;
int main()
{
int t;
cin >>t;
while(t--)
{
cin >> n;
cin >> str;
if(str[n-4]=='2'&&str[n-3]=='0'&&str[n-2]=='2'&&str[n-1]=='0')
{
cout <<"YES" << endl;
}
else if(str[0]=='2'&&str[n-3]=='0'&&str[n-2]=='2'&&str[n-1]=='0')
{
cout <<"YES" << endl;
}
else if(str[0]=='2'&&str[1]=='0'&&str[n-2]=='2'&&str[n-1]=='0')
{
cout <<"YES" << endl;
}
else if(str[0]=='2'&&str[1]=='0'&&str[2]=='2'&&str[n-1]=='0')
{
cout <<"YES" << endl;
}
else if(str[0]=='2'&&str[1]=='0'&&str[2]=='2'&&str[3]=='0')
{
cout <<"YES" << endl;
}
else
cout <<"NO" << endl;
}
return 0;
}
3、CodeForces 894A
#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#include <stdio.h>
#include <cstdio>
using namespace std;
string str;
int sum[201];
int main()
{
while(cin >> str)
{
memset(sum,0,sizeof(sum));
int num=0;
int n = str.size();
for(int i=0;i<n;i++)
{
if(str[i]=='Q')
num++;
sum[i]=num;
}
long long int ans=0;
for(int i=0;i<n;i++)
{
if(str[i]=='A')
ans += sum[i]*(sum[n-1]-sum[i]);
}
cout << ans <<endl;
}
return 0;
}
4、CodeForces 702A
#include <iostream>
using namespace std;
int main()
{
int n ;
cin >>n ;
long long int a[100010];
int p=1;
int maxi=0;
for(int i=0;i<n;i++)
{
cin >> a[i];
if(a[i]>a[i-1])
{
p++;
}
else
{
maxi = max(p,maxi);
p=1;
}
}
maxi = max(p,maxi);
cout << maxi << endl;
return 0;
}
5、CodeForces 910A
#include <iostream>
using namespace std;
const int N = 1e4+5;
int x[N],dp[N];
char str[N];
int main()
{
int n,d;
cin >>n >>d;
scanf("%s",str+1);
for(int i=1;i<=n;i++)
{
dp[i] = N;
}
dp[1] = 0;
for(int p=1;p<n;p++)
{
for(int s=1;s<=d;s++)
{
if(s+p>n)
break;
if(str[s+p]=='1')
{
dp[p+s]=min(dp[p+s],dp[p]+1);
}
}
}
if(dp[n]==N)
cout <<-1 <<endl;
else
cout << dp[n] << endl;
return 0;
}
6、CodeForces 996A
#include <iostream>
using namespace std;
long long int n;
int main()
{
cin >> n;
int h = n/100;
int r = (n%100)/20;
int p = (n%100)%20/10;
int s = (n%100)%20%10/5;
int l = n%100%20%10%5/1;
cout << h+s+r+p+l << endl;
return 0;
}
7、CodeForces 1180A
#include <iostream>
using namespace std;
long long int n;
int dp[110];
int main()
{
cin >> n;
dp[1]=1;
for(int i=2;i<=n;i++)
{
dp[i]=dp[i-1]+4*(i-1);
}
cout << dp[n] <<endl;
return 0;
}
8、CodeForces 1470A
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 3000010;
int a[N],b[N];
bool cmp(int a,int b)
{
return a > b;
}
int main()
{
int t;
cin >>t;
while(t--)
{
int n,m;
cin >> n >>m;
for(int i=1;i<=n;i++)
cin >> a[i];
for(int j=1;j<=m;j++)
cin >> b[j];
sort(a+1,a+n+1,cmp);
long long int p=1;
long long int sum=0;
for(int i=1;i<=n;i++)
{
if(a[i]>=p) sum+=b[p],p++;
else
sum+=b[a[i]];
}
cout <<sum << endl;
}
return 0;
}
9、HDU 1114
#include<iostream>
#include<algorithm>
#define inf 0x3f3f3f3f
using namespace std;
int v[600];
int w[600];
int dp[10005];
int main(){
int t;
cin>>t;
while(t--){
int a,b;
cin>>a>>b;
int k = b-a;
int n;
cin>>n;
for(int i=1;i<=n;i++)
cin>>v[i]>>w[i];
for(int i=1;i<=k;i++) dp[i] = inf;
for(int i=1;i<=n;i++)
{
for(int j = w[i];j<=k;j++)
{
dp[j] = min(dp[j-w[i]]+v[i],dp[j]);
}
}
if(dp[k]<inf) printf("The minimum amount of money in the piggy-bank is %d.\n",dp[k]);
else cout<<"This is impossible."<<endl;
}
}
10、HDU 2546
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
int a[10001];
int dp[10001];
int main()
{
int n ;
int m;
while(cin>>n&&n)
{
memset(a,0,sizeof(a));
memset(dp,0,sizeof(dp));
for(int i=0;i<n;i++)
cin >> a[i];
sort(a,a+n);
cin >> m;
for(int i=0;i<n-1;i++)
{
for(int j=m-5;j>=a[i];j--)
{
dp[j]=max(dp[j],dp[j-a[i]]+a[i]);
}
}
if(m<5)
cout << m << endl;
else
cout << m-dp[m-5]-a[n-1] << endl;
}
return 0;
}