本来打算寒假的最后几天争取看能不能把dp46道给搞定的,结果发现过年的时候不想刷题,过完年之后大家又忙着去学校吃离别的饭了,于是嘛,计划又只是一个幌子
题目:来自 hdu
分类(我是看这儿的):动态规划(46道题目)
目测开学之前是刷不完了,如果只是为了完成计划盲目的去做题,还不如不做,因为感觉那样的话,解决一个问题的本质就早已变了,如果是为了变强的话,在思维上进步就行了,做了多少多少题只能证明你编程有一段时间了,并不能证明你有多牛逼,或者说你的水平有多高,所以呢,不想做题的时候,简单地总结总结就好,快开学了,想联系的同学一起出去玩玩,出去闹闹,以后见面的日子就短了,没玩过的游戏也可以尝试尝试,毕竟每个人都有不同生活,没有一个人是平凡而简单的。
已做:30+
还剩:10+
期限:暂定
个人分类:(暂时做过的)
0-1 背包: 2602 2546 2955 1203
完全背包: 2191 1171 1248 1114
0-1 背包第k优解: 2639
多维背包: 2844(模板,二进制优化)
最优子序列:1003 1231
最长公共子序列:1159
最大上升子序列:1087
最长上升子序列:1257
贪心: 1789
简单dp:
2084(数塔) 1176(数塔变形) 2577 1421
1224 1978 2845 1864 2159 1058
最大子矩阵 1505 1506 2870 2830
dp+dfs:
1078 2571
在已经做的题目里面,我是用txt存在电脑里的,按照hdu题号排序的结果就如下:
hdu 1003 Max Sum
// 最优子序列(和最大的连续子序列)
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
#define maxn 0xfffffff
int main()
{
int t;
scanf("%d",&t);
int tag=0;
while(t--)
{
int n;
scanf("%d",&n);
int sum=0,tmp=-maxn,cnt=0,start=1,end=1,a;
for(int i=1;i<=n;i++)
{
scanf("%d",&a);
sum+=a;
if(sum>tmp)
{
tmp=sum;
start=cnt+1;
end=i;
}
if(sum<0)
{
sum=0;
cnt=i;
}
}
printf("Case %d:\n%d %d %d\n",++tag,tmp,start,end);
if(t)
printf("\n");
}
return 0;
}
hdu 1058 Humble Numbers
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
int num[5843];
int main()
{
int a=1,b=1,c=1,d=1;
num[1]=1;
for(int i=2;i<=5842;i++)
{
num[i]=min(min(num[a]*2,num[b]*3),min(num[c]*5,num[d]*7));
if(num[i]==num[a]*2) a++;
if(num[i]==num[b]*3) b++;
if(num[i]==num[c]*5) c++;
if(num[i]==num[d]*7) d++;
}
int n;
while(scanf("%d",&n)!=EOF,n)
{
if(n%10==1&&n%100!=11)
printf("The %dst humble number is %d.\n",n,num[n]);
else if(n%10==2&&n%100!=12)
printf("The %dnd humble number is %d.\n",n,num[n]);
else if(n%10==3&&n%100!=13)
printf("The %drd humble number is %d.\n",n,num[n]);
else
printf("The %dth humble number is %d.\n",n,num[n]);
}
return 0;
}
hdu 1059 Dividing
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
int dp[120010];// 20000*6
int a[7];
int v;
void ZeroOne(int cost,int weight)
{
for(int i=v;i>=cost;i--)
dp[i]=max(dp[i],dp[i-cost]+weight);
}
void Complete(int cost,int weight)
{
for(int i=cost;i<=v;i++)
dp[i]=max(dp[i],dp[i-cost]+weight);
}
void Multiple(int cost,int weight,int count)
{
if(cost*count>=v)
Complete(cost,weight);
else
{
int k=1;
while(k<count)
{
ZeroOne(k*cost,k*weight);
count-=k;
k*=2;
}
ZeroOne(count*cost,count*weight);
}
}
int main()
{
int tmp=0;
while(scanf("%d%d%d%d%d%d",&a[1],&a[2],&a[3],&a[4],&a[5],&a[6])!=EOF)
{
if(!(a[1]||a[2]||a[3]||a[4]||a[5]||a[6]))
break;
printf("Collection #%d:\n",++tmp);
v=0;
for(int i=1;i<=6;i++)
{
v+=a[i]*i;
}
if(v&1)
printf("Can't be divided.\n");
else
{
v/=2;
memset(dp,0,sizeof(dp));
for(int i=1;i<=6;i++)
Multiple(i,i,a[i]);
if(dp[v]==v)
printf("Can be divided.\n");
else
printf("Can't be divided.\n");
}
printf("\n");
}
return 0;
}
hdu 1069 Monkey and Banana
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
struct block
{
int x,y,z;
}B[100];
int cnt[3];
int dp[100];
void init(block *B,int a,int b,int c)
{// 这个坑了我好久,突然想起之前写过一个很sb的swap
B->x=max(a,b);
B->y=min(a,b);
B->z=c;
}
bool cmp(block p,block q)
{
if(p.x==q.x)
return p.y>q.y;
return p.x>q.x;
}
int main()
{
int n;
int tag=0;
while(scanf("%d",&n),n)
{
int tmp=0;
for(int i=1;i<=n;i++)
{
for(int j=0;j<3;j++)
scanf("%d",&cnt[j]);
init(&B[++tmp],cnt[2],cnt[1],cnt[0]);
init(&B[++tmp],cnt[1],cnt[0],cnt[2]);
init(&B[++tmp],cnt[2],cnt[0],cnt[1]);
}
sort(B+1,B+tmp+1,cmp);
int ans=0;
memset(dp,0,sizeof(dp));
for(int i=1;i<=tmp;i++)
{
int now=0;
for(int j=i-1;j>=0;j--)
if(B[i].x<B[j].x&&B[i].y<B[j].y)
now=max(now,dp[j]);
dp[i]=B[i].z+now;
ans=max(ans,dp[i]);
//开始写的是直接输出dp[tmp],WA了,因为最后一组的三个可以不是按height排的
// 可以写 ans=max(dp[tmp],dp[tmp-1],dp[tmp-2])
}
printf("Case %d: maximum height = %d\n",++tag,ans);
}
return 0;
}
hdu 1078 FatMouse and Cheese
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
int dp[110][110],map[110][110];
int move[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
int n,k;
int dfs(int x,int y)
{
if(dp[x][y])
return dp[x][y];
int temp=0;
for(int i=0;i<4;i++)
for(int j=1;j<=k;j++)
{
int xx=x+move[i][0]*j;
int yy=y+move[i][1]*j;
if(xx<=n&&xx>=1&&yy<=n&&yy>=1&&map[xx][yy]>map[x][y])
{
int cnt=dfs(xx,yy);
temp=max(temp,cnt);
}
}
dp[x][y]=temp+map[x][y];
return dp[x][y];
}
int main()
{
while(scanf("%d%d",&n,&k),n!=-1||k!=-1)
{
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
scanf("%d",&map[i][j]);
dp[i][j]=0;
}
printf("%d\n",dfs(1,1));
}
return 0;
}
hdu 1087 Super Jumping! Jumping! Jumping!
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int dp[1010],v[1010];
int main()
{
int n;
while(scanf("%d",&n),n)
{
for(int i=1;i<=n;i++)
{
scanf("%d",&v[i]);
dp[i]=v[i];
for(int j=1;j<i;j++)
if(v[j]<v[i])
dp[i]=max(dp[i],dp[j]+v[i]);
}
int mi=0;
for(int i=1;i<=n;i++)
mi=max(mi,dp[i]);
printf("%d\n",mi);
}
return 0;
}
hdu 1114 Piggy-Bank
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
using namespace std;
int w[510],v[510];
int dp[10010];
int E,F,V;
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&E,&F);
V=F-E;
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d%d",&v[i],&w[i]);
memset(dp,0x3f,sizeof(dp));
int inf=dp[1];
dp[0]=0;
for(int i=1;i<=n;i++)
for(int j=w[i];j<=V;j++)
dp[j]=min(dp[j],dp[j-w[i]]+v[i]);
if(dp[V]<inf)
printf("The minimum amount of money in the piggy-bank is %d.\n",dp[V]);
else
printf("This is impossible.\n");
}
return 0;
}
hdu 1159 Common Subsequence
#include <cstdio>
#include <cstring>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
string s1,s2;
int dp[1000][1000];
int main()
{
while(cin>>s1>>s2)
{
memset(dp,0,sizeof(dp));
for(int i=1;i<=s1.size();i++)
for(int j=1;j<=s2.size();j++)
{
if(s1[i-1]==s2[j-1])
dp[i][j]=dp[i-1][j-1]+1;
else
dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
}
printf("%d\n",dp[s1.size()][s2.size()]);
}
return 0;
}
hdu 1171 Big Event in HDU
#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
#define maxn 125005
int dp[maxn];// 50种*50value*100kind/2
int v[55],kind[105];
int main()
{
int n;
while(scanf("%d",&n)!=EOF,n>=0)
{
int ans=0;
for(int i=1;i<=n;i++)
{
scanf("%d%d",&v[i],&kind[i]);
ans+=v[i]*kind[i];
}
int tmp=ans/2;
tmp=max(ans-tmp,tmp);
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;i++)
for(int j=1;j<=kind[i];j++)
for(int k=tmp;k>=v[i];k--)
dp[k]=max(dp[k],dp[k-v[i]]+v[i]);
printf("%d %d\n",max(dp[tmp],ans-dp[tmp]),min(dp[tmp],ans-dp[tmp]));
}
return 0;
}
hdu 1176 免费馅饼
// 时间当做层数,馅饼当做数,就转换成数塔的题了
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int dp[100010][12];
int main()
{
int n;
while(scanf("%d",&n),n!=0)
{
int a,b,tmp=0;
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;i++)
{
scanf("%d%d",&a,&b);
dp[b][a]++;
tmp=max(tmp,b);
}
for(int i=tmp-1;i>=0;i--)
{
dp[i][0]+=max(dp[i+1][0],dp[i+1][1]);
for(int j=1;j<=10;j++)
dp[i][j]+=max(dp[i+1][j-1],max(dp[i+1][j],dp[i+1][j+1]));
}
printf("%d\n",dp[0][5]);
}
return 0;
}
hdu 1203 I NEED A OFFER!
// 至少收到一份offer的(最大)概率
// 反命题就是 一份都没收到的(最小)概率
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
#define maxn 10001
double dp[maxn];
int v[maxn];
double p[maxn];
int main()
{
int m,n;
while(scanf("%d%d",&m,&n)!=EOF,m+n)
{
for(int i=1;i<=n;i++)
scanf("%d%lf",&v[i],&p[i]);
for(int i=0;i<=maxn;i++)//开始写的是从1开始,WA一次
dp[i]=1;
for(int i=1;i<=n;i++)
for(int j=m;j>=v[i];j--)
dp[j]=min(dp[j],dp[j-v[i]]*(1-p[i]));
printf("%.1lf%%\n",(1-dp[m])*100);
}
return 0;
}
hdu 1224 Free DIY Tour
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
int dp[105],v[105],father[105];
int map[105][105];
void show(int n)
{
if(n==father[n])
printf("%d",n);
else
{
show(father[n]);
printf("->%d",n);
}
}
int main()
{
int t,tag=0;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&v[i]);
father[i]=i;
}
v[n+1]=0;
memset(map,0,sizeof(map));
int m,a,b;
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
scanf("%d%d",&a,&b);
map[a][b]=1;
}
memset(dp,0,sizeof(dp));
for(int i=1;i<=n+1;i++)
for(int j=1;j<i;j++)
{
if(map[j][i]&&dp[j]+v[i]>dp[i])
{
dp[i]=dp[j]+v[i];
father[i]=j;
}
}
printf("CASE %d#\n",++tag);
printf("points : %d\n",dp[n+1]);
printf("circuit : ");
show(father[n+1]);
printf("->1\n");
if(t)
printf("\n");
}
return 0;
}
hdu 1231 最大连续子序列
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=10001;
int a[maxn];
int main()
{
int n;
while(scanf("%d",&n),n)
{
int tag=0;
int start=1,end=1,sum=0,tmp=0,mx=-0xfffffff;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
sum+=a[i];
if(a[i]>=0)
tag=1;
if(sum>mx)
{
start=tmp+1;
end=i;
mx=sum;
}
if(sum<0)
{
tmp=i;
sum=0;
}
}
if(tag)
printf("%d %d %d\n",mx,a[start],a[end]);
else
printf("0 %d %d\n",a[1],a[n]);
}
return 0;
}
hdu 1248 寒冰王座
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int dp[10001];
int v[4]={0,150,200,350};
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
memset(dp,0,sizeof(dp));
for(int i=1;i<=3;i++)
for(int j=v[i];j<=n;j++)
dp[j]=max(dp[j],dp[j-v[i]]+v[i]);
printf("%d\n",n-dp[n]);
}
return 0;
}
hdu 1257 最少拦截系统
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn=30010;
int dp[maxn];
int a[maxn];
int LIS(int *a,int n)
{
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;i++)
{
int tmp=dp[i];
for(int j=1;j<i;j++)
{
if(tmp<dp[j]&&a[i]>a[j])
{
tmp=dp[j];
}
}
dp[i]=tmp+1;
}
int ans=0;
for(int i=1;i<=n;i++)
ans=max(ans,dp[i]);
return ans;
}
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
printf("%d\n",LIS(a,n));
}
return 0;
}
hdu 1421 搬寝室
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
int dp[2002][1001];
int v[2002];
int main()
{
int n,k;
while(scanf("%d%d",&n,&k)!=EOF)
{
for(int i=1;i<=n;i++)
scanf("%d",&v[i]);
sort(v+1,v+n+1);
for(int i=1;i<n;i++)
{
v[i]=v[i+1]-v[i];
v[i]*=v[i];
}
memset(dp,0x7f,sizeof(dp));
// memset原本是用来处理字符串的,最大赋值为0x7f,对应一个10^10数量级的数
for(int i=0;i<=n;i++)
dp[i][0]=0;
for(int i=2;i<=n;i++)
for(int j=1;2*j<=i;j++)
dp[i][j]=min(dp[i-1][j],dp[i-2][j-1]+v[i-1]);
printf("%d\n",dp[n][k]);
}
return 0;
}
hdu 1505 City Game
// hdu2506的变形
// 看其中一排,把这排及下面的数中可以的“F”累计存在数组里
// 然后剩下的就是和hdu2506一样的步骤了
// 输入好坑 之前用%*c%c WA了,然后改用scanf(“%s”)过了
// 说明中间的空格可能不是连续的,不能默认为只有一个
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int maxn=1001;
char map[maxn][maxn];
int a[maxn];
int l[maxn],r[maxn];
int m,n;
int solve()
{
l[1]=1;
for(int i=2;i<=n;i++)
{
int tmp=i;
while(tmp>1&&a[i]<=a[tmp-1])
tmp=l[tmp-1];
l[i]=tmp;
}
r[n]=n;
for(int i=n-1;i>=1;i--)
{
int tmp=i;
while(tmp<n&&a[i]<=a[tmp+1])
tmp=r[tmp+1];
r[i]=tmp;
}
int ans=0;
for(int i=1;i<=n;i++)
ans=max(ans,(r[i]-l[i]+1)*a[i]);
return ans;
}
char str[10];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&m,&n);
for(int i=1;i<=m;i++)
for(int j=1;j<=n;j++)
{
scanf("%s",str);
map[i][j]=str[0];
}
int ans=0;
for(int i=1;i<=m;i++)
{
memset(a,0,sizeof(a));
for(int k=1;k<=n;k++)
{
for(int j=i;j<=m;j++)
{
if(map[j][k]=='F')
a[k]++;
if(map[j][k]=='R')
break;
}
}
ans=max(ans,solve());
}
printf("%d\n",3*ans);
}
return 0;
}
hdu 1506 Largest Rectangle in a Histogram
// 把某根柱子周围能够延伸到的范围记下来(比旁边都要矮)
// 利用递归记录范围,避免大量的重复
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int maxn=100010;
long long a[maxn];
int r[maxn],l[maxn];
int main()
{
int n;
while(scanf("%d",&n),n)
{
for(int i=1;i<=n;i++)
scanf("%I64d",&a[i]);
l[1]=1;
for(int i=2;i<=n;i++)
{
int tmp=i;
while(tmp>1&&a[i]<=a[tmp-1])
tmp=l[tmp-1];
l[i]=tmp;
}
r[n]=n;
for(int i=n-1;i>=1;i--)
{
int tmp=i;
while(tmp<n&&a[i]<=a[tmp+1])
tmp=r[tmp+1];
r[i]=tmp;
}
long long ans=0;
for(int i=1;i<=n;i++)
ans=max(ans,(r[i]-l[i]+1)*a[i]);
printf("%I64d\n",ans);
}
return 0;
}
hdu 1789 Doing Homework again
// 贪心
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
struct S
{
int time,value;
};
S s[1010];
int vis[1010];
bool cmp(S a,S b)
{
if(a.value==b.value)
return a.time<b.time;
return a.value>b.value;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&s[i].time);
for(int i=1;i<=n;i++)
scanf("%d",&s[i].value);
sort(s+1,s+n+1,cmp);
int ans=0;
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++)
{
if(!vis[s[i].time])
vis[s[i].time]=1;
else
{
int tag=0;
for(int j=s[i].time;j>=1;j--)
{
if(!vis[j])
{
vis[j]=1;
tag=1;
break;
}
}
if(!tag)
{
for(int j=n;j>s[i].time;j--)
{
if(!vis[j])
{
vis[j]=1;
ans+=s[i].value;
break;
}
}
}
}
}
printf("%d\n",ans);
}
return 0;
}
hdu 1864 最大报销额
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
double v[31];
double dp[31];
int main()
{
double M;
int N;
while(scanf("%lf%d",&M,&N),N)
{
for(int i=1;i<=N;i++)
{
int n;
scanf("%d",&n);
int tag=0;
double value=0;
int v_a=0,v_b=0,v_c=0;
while(n--)
{
char c;
double tmp;
scanf("%*c%c:%lf",&c,&tmp);
if(c>'C'||c<'A')
tag=1;
value+=tmp;
if(c=='A')
v_a+=tmp;
if(c=='B')
v_b+=tmp;
if(c=='C')
v_c+=tmp;
if(value>1000||v_a>600||v_b>600||v_c>600)
tag=1;
}
if(tag)
v[i]=0;
else
v[i]=value;
}
memset(dp,0,sizeof(dp));
for(int i=1;i<=N;i++)
for(int j=i;j>=1;j--)
dp[j]=max(dp[j],dp[j-1]+v[i]);
double ans=0;
for(int i=1;i<=N;i++)
if(dp[i]<=M)
{
ans=max(ans,dp[i]);
}
printf("%.2lf\n",ans);
}
return 0;
}
hdu 1978 How many ways
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
int dp[210][210];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int m,n;
scanf("%d%d",&m,&n);
memset(dp,0,sizeof(dp));
dp[1][1]=1;
for(int i=1;i<=m;i++)
for(int j=1;j<=n;j++)
{
int cnt;
scanf("%d",&cnt);
for(int k=0;k<=cnt;k++)
for(int l=0;l+k<=cnt;l++)
{
if(l==0&&k==0)
continue;
dp[i+k][j+l]=(dp[i][j]+dp[i+k][j+l])%10000;
}
}
printf("%d\n",dp[m][n]);
}
return 0;
}
hdu 2084 数塔
// 简单dp
// 从倒数第二层开始往上走
// 将每个点左右节点中的最大值累计给自己往上传
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int dp[110][110];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;i++)
for(int j=1;j<=i;j++)
scanf("%d",&dp[i][j]);
for(int i=n-1;i>=1;i--)
for(int j=1;j<=n;j++)
dp[i][j]+=max(dp[i+1][j],dp[i+1][j+1]);
printf("%d\n",dp[1][1]);
}
return 0;
}
hdu 2159 FATE
// 二维背包
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
int n,m,K,s;
int exp[101],tol[101];
int dp[101][101];
int main()
{
while(scanf("%d%d%d%d",&n,&m,&K,&s)!=EOF)
{
int tag=0,ans;
for(int i=1;i<=K;i++)
scanf("%d%d",&exp[i],&tol[i]);
memset(dp,0,sizeof(dp));
for(int i=1;i<=m;i++)
{
for(int j=1;j<=s;j++)
{
for(int k=1;k<=K;k++)
{
if(i>=tol[k])
dp[i][j]=max(dp[i][j],dp[i-tol[k]][j-1]+exp[k]);
}
}
if(dp[i][s]>=n)
{
ans=m-i;
tag=1;
break;
}
}
if(!tag)
printf("-1\n");
else
printf("%d\n",ans);
}
return 0;
}
hdu 2191 悼念512汶川大地震遇难同胞——珍惜现在,感恩生活
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
int dp[101],v[101],w[101],num[101];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int m,n;
scanf("%d%d",&m,&n);
for(int i=1;i<=n;i++)
scanf("%d%d%d",&v[i],&w[i],&num[i]);
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;i++)
for(int j=1;j<=num[i];j++)
for(int k=m;k>=v[i];k--)
dp[k]=max(dp[k],dp[k-v[i]]+w[i]);
printf("%d\n",dp[m]);
}
return 0;
}
hdu 2546 饭卡
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
const int maxn=1010;
int dp[maxn],a[maxn];
int main()
{
int n;
while(scanf("%d",&n),n)
{
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
int m;
scanf("%d",&m);
if(m<5)
printf("%d\n",m);
else
{
memset(dp,0,sizeof(dp));
sort(a+1,a+n+1);
for(int i=1;i<=n-1;i++)
for(int j=m-5;j>=a[i];j--)
dp[j]=max(dp[j],dp[j-a[i]]+a[i]);
printf("%d\n",m-dp[m-5]-a[n]);
}
}
return 0;
}
hdu 2571 命运
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
int map[21][1001],vis[21][1001];
int m,n;
int dfs(int x,int y)
{
if(vis[x][y]!=-1001)
return vis[x][y];
int tmp;
if(x==1&&y==1)
tmp=map[1][1];
else if(y==1&&x>1)
tmp=map[x][y]+dfs(x-1,y);
else if(x==1&&y>1)
{
tmp=dfs(x,y-1);
for(int k=y-1;k>=1;k--)
if(y%k==0)
tmp=max(tmp,dfs(x,k));
tmp+=map[x][y];
}
else
{
tmp=max(dfs(x-1,y),dfs(x,y-1));
for(int k=y-1;k>=1;k--)
if(y%k==0)
tmp=max(tmp,dfs(x,k));
tmp+=map[x][y];
}
vis[x][y]=tmp;
return vis[x][y];
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
scanf("%d",&map[i][j]);
vis[i][j]=-1001;
}
printf("%d\n",dfs(n,m));
}
return 0;
}
hdu 2577 How to Type
#include <cstdio>
#include <cstring>
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
string s;
int dp[110][2];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
cin>>s;
memset(dp,0,sizeof(dp));
dp[0][1]=1;// 表示开始是锁是开的
for(int i=0;i<s.size();i++)
{
if(s[i]>='a'&&s[i]<='z')
{
dp[i+1][0]=min(dp[i][0]+1,dp[i][1]+2);
dp[i+1][1]=min(dp[i][0]+2,dp[i][1]+2);
}
else
{
dp[i+1][0]=min(dp[i][0]+2,dp[i][1]+2);
dp[i+1][1]=min(dp[i][0]+2,dp[i][1]+1);
}
}
printf("%d\n",min(dp[s.size()][0],dp[s.size()][1]+1));
}
return 0;
}
hdu 2602 Bone Collector
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn=1010;
int v[maxn],w[maxn];
int dp[maxn];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n,V;
scanf("%d%d",&n,&V);
for(int i=1;i<=n;i++)
scanf("%d",&w[i]);
for(int i=1;i<=n;i++)
scanf("%d",&v[i]);
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;i++)
for(int j=V;j>=v[i];j--)
dp[j]=max(dp[j],dp[j-v[i]]+w[i]);
printf("%d\n",dp[V]);
}
return 0;
}
hdu 2639 Bone Collector II
// 0-1背包第k优解
// 将两个for里面的状态用队列标记起来
// 然后将这个有序队列进行合并(取(2k-2)项),取k时的情况
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=1005;
int val[maxn],v[maxn];
int f[maxn][35];
int A[35],B[35];
int N,V,K;
void solve()
{
int k;
memset(f,0,sizeof(f));
for(int i=1;i<=N;i++)
for(int j=V;j>=v[i];j--)
{
for(k=1;k<=K;k++)
{
A[k]=f[j-v[i]][k]+val[i];
B[k]=f[j][k];
}
A[k]=-1,B[k]=-1;//覆盖掉无所谓
int a=1,b=1,c=1;
while(c<=K&&(A[a]!=-1||B[b]!=-1))
{
if(A[a]>B[b])
f[j][c]=A[a++];
else
f[j][c]=B[b++];
if(f[j][c]!=f[j][c-1])
c++;
}
}
printf("%d\n",f[V][K]);
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d%d%d",&N,&V,&K);
for(int i=1;i<=N;i++)
scanf("%d",&val[i]);
for(int i=1;i<=N;i++)
scanf("%d",&v[i]);
solve();
}
return 0;
}
hdu 2830 Matrix Swapping II
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int maxn=1010;
int map[maxn][maxn];
int tag[maxn];
char str[maxn][maxn];
int main()
{
int m,n;
while(scanf("%d%d",&m,&n)!=EOF)
{
memset(map,0,sizeof(map));
for(int i=1;i<=m;i++)
scanf("%s",str[i]);
for(int i=1;i<=m;i++)
for(int j=0;j<n;j++)
if(str[i][j]=='1')
map[i][j+1]=map[i-1][j+1]+1;
else
map[i][j+1]=0;
int ans=0;
for(int i=1;i<=m;i++)
{
memset(tag,0,sizeof(tag));
for(int j=1;j<=n;j++)
tag[map[i][j]]++;
for(int j=i;j>=0;j--)
tag[j]+=tag[j+1];//逆序,把比它高的累计起来
for(int j=1;j<=i;j++)
ans=max(ans,tag[j]*j);
}
printf("%d\n",ans);
}
return 0;
}
//还真的用空间换取了时间
//下面的代码用时间是前面的十倍 ==
// 空间就是少了那个char str[maxn][maxn]
/*
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int maxn=1010;
int map[maxn][maxn];
int tag[maxn];
char str[maxn][maxn];
int main()
{
int m,n;
while(scanf("%d%d",&m,&n)!=EOF)
{
memset(map,0,sizeof(map));
for(int i=1;i<=m;i++)
scanf("%s",str[i]);
for(int i=1;i<=m;i++)
for(int j=0;j<n;j++)
if(str[i][j]=='1')
map[i][j+1]=map[i-1][j+1]+1;
else
map[i][j+1]=0;
int ans=0;
for(int i=1;i<=m;i++)
{
memset(tag,0,sizeof(tag));
for(int j=1;j<=n;j++)
tag[map[i][j]]++;
for(int j=i;j>=0;j--)
tag[j]+=tag[j+1];//逆序,把比它高的累计起来
for(int j=1;j<=i;j++)
ans=max(ans,tag[j]*j);
}
printf("%d\n",ans);
}
return 0;
}
*/
hdu 2844 Coins
// 擦,dp题竟然也用模板
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
int dp[100010];
int a[1010],c[1010];
int v;
void ZeroOne(int cost,int weight)
{
for(int i=v;i>=cost;i--)
dp[i]=max(dp[i],dp[i-cost]+weight);
}
void Complete(int cost,int weight)
{
for(int i=cost;i<=v;i++)
dp[i]=max(dp[i],dp[i-cost]+weight);
}
void Multiple(int cost,int weight,int count)
{
if(cost*count>=v)
Complete(cost,weight);
else
{
int k=1;
while(k<count)
{
ZeroOne(k*cost,k*weight);
count-=k;
k*=2;
}
ZeroOne(count*cost,count*weight);
}
}
int main()
{
int m,n;
while(scanf("%d%d",&n,&m),m||n)
{
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=1;i<=n;i++)
scanf("%d",&c[i]);
memset(dp,0,sizeof(dp));
v=m;
for(int i=1;i<=n;i++)
Multiple(a[i],a[i],c[i]);
int ans=0;
for(int i=1;i<=m;i++)//跟hdu big event那题一样,cost=weight,求最多能装到多少
if(dp[i]==i)
ans++;
printf("%d\n",ans);
}
return 0;
}
hdu 2845 Beans
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn=200010;
int a[maxn],b[maxn];
int main()
{
int m,n;
while(scanf("%d%d",&m,&n)!=EOF)
{
a[0]=b[0]=0;
for(int i=1;i<=m;i++)
{
for(int j=1;j<=n;j++)
scanf("%d",&a[j]);
for(int j=2;j<=n;j++)
a[j]=max(a[j-1],a[j-2]+a[j]);
b[i]=a[n];
}
for(int i=2;i<=m;i++)
b[i]=max(b[i-1],b[i-2]+b[i]);
printf("%d\n",b[m]);
}
return 0;
}
hdu 2870 Largest Submatrix
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=1010;
int a[maxn],l[maxn],r[maxn];
int map[maxn][maxn];
char vis[maxn][maxn];
int solution(int col)
{
l[1]=1;
for(int i=2;i<=col;i++)
{
int tmp=i;
while(tmp>1&&a[i]<=a[tmp-1])
tmp=l[tmp-1];
l[i]=tmp;
}
r[col]=col;
for(int i=col-1;i>=1;i--)
{
int tmp=i;
while(tmp<col&&a[i]<=a[tmp+1])
tmp=r[tmp+1];
r[i]=tmp;
}
int ans=0;
for(int i=1;i<=col;i++)
ans=max(ans,(r[i]-l[i]+1)*a[i]);
return ans;
}
int solve(int row,int col)
{
int ans=0;
for(int i=1;i<=row;i++)
{
memset(a,0,sizeof(a));
for(int k=1;k<=col;k++)
{
for(int j=i;j<=row;j++)
{
if(map[j][k]==1)
a[k]++;
else
break;
}
}
ans=max(ans,solution(col));
}
return ans;
}
int main()
{
int m,n;
while(scanf("%d%d",&m,&n)!=EOF)
{
int ans=0;
for(int i=1;i<=m;i++)
scanf("%s",vis[i]);
for(int i=1;i<=m;i++)
for(int j=0;j<n;j++)
if(vis[i][j]=='x'||vis[i][j]=='b'||vis[i][j]=='c')
map[i][j+1]=0;
else
map[i][j+1]=1;
ans=max(ans,solve(m,n));
for(int i=1;i<=m;i++)
for(int j=0;j<n;j++)
if(vis[i][j]=='y'||vis[i][j]=='a'||vis[i][j]=='c')
map[i][j+1]=0;
else
map[i][j+1]=1;
ans=max(ans,solve(m,n));
for(int i=1;i<=m;i++)
for(int j=0;j<n;j++)
if(vis[i][j]=='w'||vis[i][j]=='a'||vis[i][j]=='b')
map[i][j+1]=0;
else
map[i][j+1]=1;
ans=max(ans,solve(m,n));
printf("%d\n",ans);
}
return 0;
}
hdu 2955 Robberies
// 给定抢多少钱不被抓的概率
// 求给定概率内能抢到的最多钱(最大概率不被抓)
// 反命题就是钱尽量多,被抓的最大概率
// attention: init dp[0]=1;else dp[i]=0;
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn=10010;
int v[maxn],n;
double dp[maxn],p[maxn],P;
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int sum=0;
scanf("%lf%d",&P,&n);
for(int i=1;i<=n;i++)
{
scanf("%d%lf",&v[i],&p[i]);
sum+=v[i];
}
memset(dp,0,sizeof(dp));
dp[0]=1;
for(int i=1;i<=n;i++)
for(int j=sum;j>=v[i];j--)
dp[j]=max(dp[j],dp[j-v[i]]*(1-p[i]));
for(int i=sum;i>=0;i--)
if(dp[i]>=1-P)
{
printf("%d\n",i);
break;
}
}
return 0;
}
还剩下:
hdu 1024 Max Sum Plus Plus
hdu 1081 To The Max
hdu 1025 Constructing Roads In JGShining's Kingdom
hdu 2059 龟兔赛跑
hdu 1158 Employment Planning
hdu 1080 Human Gene Functions
hdu 1160 FatMouse's Speed
hdu 1074 Doing Homework
hdu 1422 重温世界杯
hdu 1300 Pearls
hdu 1501 Zipper
hdu 1227 Fast Food
hdu 3008 Warcraft
hdu 1502 Regular Words
hdu 1503 Advanced Fruits
屌丝嘛,平时多笑笑就好,开开心心的,csdn论坛上的屌丝传奇,推荐大家去乐乐:
【转】屌丝传奇(诞生篇)
【转】屌丝传奇(围观篇)
当然,剩下的还是应该逐步击破,但一定不可以为了做题而强迫自己看别人的代码从而A掉。
其实,我一直在纠结强迫自己是好事还是坏事,但从长远的看来,有些问题还是很明显的。
总有一个人,你骗得了全世界也不舍得骗,那个人就是我们自己。