P1855 榨取kkksc03 - 洛谷
简单的二维01背包
#include<bits/stdc++.h>
#define ll long long
#define N 1005
using namespace std;
int t,a,b,dp[205][205],n,m;
int main()
{
cin>>t>>n>>m;
while(t--){
cin>>a>>b;
for(int i=n;i>=a;i--){
for(int j=m;j>=b;j--){
dp[i][j]=max(dp[i][j],dp[i-a][j-b]+1);
}
}
}
cout<<dp[n][m];
return 0;
}
P1833 樱花 - 洛谷
混合背包问题,分类即可
#include<bits/stdc++.h>
#define ll long long
#define N 1005
using namespace std;
int n,a,b,c,d,t,dp[1005];
char ch;
int main()
{
cin>>a>>ch>>b>>c>>ch>>d>>t;
n=c*60+d-a*60-b;
while(t--){
cin>>a>>b>>c;
if(c==0){
for(int i=a;i<=n;i++){
dp[i]=max(dp[i],dp[i-a]+b);
}
}
else{
for(int j=1;j<=c;j++){
for(int i=n;i>=a;i--){
dp[i]=max(dp[i],dp[i-a]+b);
}
}
}
}
cout<<dp[n];
return 0;
}
P1203 [USACO1.1] 坏掉的项链 Broken Necklace - 洛谷
模拟题,细节惊人
1.如果断开的地方开头是白色珠子,如何处理?
2.如果全是白色珠子的情况。
#include<bits/stdc++.h>
using namespace std;
string s;
int n,ans;
void suan(int l,int r){
int sum=0;
while(s[l]=='w'&&l<r){
l++;
sum++;
}
while(s[r]=='w'&&r>l){
r--;
sum++;
}
if(r==l+1){
ans=max(ans,sum);
return;
}
char left=s[l],right=s[r];
for(;l<=r;l++){
if(s[l]!=left&&s[l]!='w'){
l--;
break;
}
else{
sum++;
}
}
for(;r>l;r--){
if(s[r]!=right&&s[r]!='w') break;
else sum++;
}
ans=max(ans,sum);
}
int main()
{
cin>>n>>s;
if(n==1){
cout<<1;
return 0;
}
s=s+s;
for(int i=0;i<n;i++){
suan(i,i+n-1);
}
cout<<ans;
return 0;
}
P1103 书本整理 - 洛谷
先按高度排序书籍。
令 m = n - m(m 表示保留的书数)。
定义 dp[i][j] 表示以第 i 本书为最后一本,且总共选择 j 本书(包括 i)时的最小不整齐度。
初始化 dp[i][1] = 0(只选一本书时,不整齐度为 0)。
三重循环更新 dp:
i 从 1 到 n(当前书)。
j 从 1 到 i-1(前一本书)。
k 从 1 到 min(j, m-1)(j 之前已选 k 本书)。
状态转移:dp[i][k+1] = min(dp[i][k+1], dp[j][k] + abs(arr[i].w - arr[j].w))。
最后取 min(dp[i][m]) 作为答案。
还有个小细节请看https://www.luogu.com.cn/discuss/1093824,是关于0x3f的坑
#include<bits/stdc++.h>
using namespace std;
struct book{
int h,w;
}arr[105];
int n,m,dp[105][105];
bool cmp(book &s1,book &s2){
return s1.h<s2.h;
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>arr[i].h>>arr[i].w;
}
sort(arr+1,arr+1+n,cmp);
m=n-m;
memset(dp,0x3f,sizeof(dp));
for(int i=1;i<=n;i++){
dp[i][1]=0;
for(int j=1;j<i;j++){
for(int k=1;k<=min(j,m-1);k++){
dp[i][k+1]=min(dp[i][k+1],dp[j][k]+abs(arr[i].w-arr[j].w));
}
}
}
int ans=0x3f3f3f;
for(int i=1;i<=n;i++){
ans=min(ans,dp[i][m]);
}
cout<<ans;
return 0;
}
P5365 [SNOI2017] 英雄联盟 - 洛谷
多重背包,注意循环遍历的次序,先是遍历物品,再体积,再是件数。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
struct point{
ll k,c;
}arr[10000];
ll n,m,dp[300005],sum;
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>arr[i].k;
}
for(int i=1;i<=n;i++){
cin>>arr[i].c;
sum+=arr[i].c*arr[i].k;
}
dp[0]=1;
for(ll i=1;i<=n;i++){
for(ll j=sum;j>=0;j--){
for(int k=1;k<=arr[i].k&&k*arr[i].c<=j;k++){
dp[j]=max(dp[j],dp[j-k*arr[i].c]*k);
}
}
}
for(ll i=1;i<=sum;i++){
if(dp[i]>=m){
cout<<i;
break;
}
}
return 0;
}
P4141 消失之物 - 洛谷
去掉一个物品就是逆操作,注意遍历的顺序。还有要不断取模,数会很大。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int n,m,arr[2005],dp[2005],ans[2005];
int main()
{
cin>>n>>m;
dp[0]=1;
for(int i=1;i<=n;i++){
cin>>arr[i];
for(int j=m;j>=arr[i];j--){
dp[j]+=dp[j-arr[i]];
dp[j]%=10;
}
}
for(int i=1;i<=n;i++){
memcpy(ans,dp,sizeof(dp));
for(int j=arr[i];j<=m;j++){
ans[j]=(ans[j]-ans[j-arr[i]]+10)%10;
}
for(int j=1;j<=m;j++){
cout<<ans[j]%10;
}
cout<<endl;
}
return 0;
}
P1541 [NOIP 2010 提高组] 乌龟棋 - 洛谷
此题更像是递推。以四种棋的数目为下标,确定每种组合的状态。记忆化搜索也可。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll n,m,v[355],dp[41][41][41][41],num[5],a;
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>v[i];
}
while(m--){
cin>>a;
num[a]++;
}
dp[0][0][0][0]=v[1];
for(int i=0;i<=num[1];i++){
for(int j=0;j<=num[2];j++){
for(int k=0;k<=num[3];k++){
for(int p=0;p<=num[4];p++){
int now=1+i+j*2+k*3+4*p;
if(i!=0) dp[i][j][k][p]=max(dp[i][j][k][p],dp[i-1][j][k][p]+v[now]);
if(j!=0) dp[i][j][k][p]=max(dp[i][j][k][p],dp[i][j-1][k][p]+v[now]);
if(k!=0) dp[i][j][k][p]=max(dp[i][j][k][p],dp[i][j][k-1][p]+v[now]);
if(p!=0) dp[i][j][k][p]=max(dp[i][j][k][p],dp[i][j][k][p-1]+v[now]);
}
}
}
}
cout<<dp[num[1]][num[2]][num[3]][num[4]];
return 0;
}
P1168 中位数 - 洛谷
此题博主用了奇巧淫技vector,二分查找+插入可让vector爆发出接近树形结构的性能。只是针对数据不强,如果数据特殊设计过就没法过。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
vector<ll>arr;
int main()
{
ll n,a;
scanf("%lld",&n);
for(int i=1;i<=n;i++){
scanf("%lld",&a);
arr.insert(lower_bound(arr.begin(),arr.end(),a),a);
if(i%2==1){
printf("%lld\n",arr[i/2]);
}
}
return 0;
}