# 目标50道题啦~~，目前50/50

## 1.合唱队形

LIS模板题，这道题只要正着求一遍LIS，倒着求一遍LIS，然后求max即可，注意因为求了两次LIS，一定会有一个人是被计算了两次的，所以在求max的时候要记得-1

#include <cstdio>
#include <cstring>
#define ll int
#define inf 1<<30
#define il inline
il ll max(ll x,ll y){return x>y?x:y;}
il ll min(ll x,ll y){return x<y?x:y;}
il ll abs(ll x){return x>0?x:-x;}
il void swap(ll &x,ll &y){ll t=x;x=y;y=t;}
x=0;ll f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-f;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
x*=f;
}
il void print(ll x){if(x<0)putchar('-');x=abs(x);if(x>9)print(x/10);putchar(x%10+'0');}
il void writeln(ll x){if(x<0)putchar('-');x=abs(x);print(x);putchar('\n');}
il void write(ll x){if(x<0)putchar('-');x=abs(x);print(x);putchar(' ');}
using namespace std;
#define N 110
ll n,a[N],f1[N],f2[N];
int main(){
for(ll i=1;i<=n;i++){
f1[i]=1;
for(ll j=1;j<i;j++){
if(a[i]>a[j])f1[i]=max(f1[i],f1[j]+1);
}
}
for(ll i=n;i;i--){
f2[i]=1;
for(ll j=i+1;j<=n;j++){
if(a[i]>a[j])f2[i]=max(f2[i],f2[j]+1);
}
}
ll ans=0;
for(ll i=1;i<=n;i++)ans=max(ans,f1[i]+f2[i]-1);
writeln(n-ans);
return 0;
}

## 2.导弹拦截

#### 1.O(n2)做法

#include <cstdio>
#include <cstring>
#include <algorithm>
#define ll int
#define inf 1<<30
#define il inline
il ll max(ll x,ll y){return x>y?x:y;}
il ll min(ll x,ll y){return x<y?x:y;}
il ll abs(ll x){return x>0?x:-x;}
il void swap(ll &x,ll &y){ll t=x;x=y;y=t;}
x=0;ll f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-f;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
x*=f;
}
il void print(ll x){if(x<0)putchar('-');x=abs(x);if(x>9)print(x/10);putchar(x%10+'0');}
il void writeln(ll x){if(x<0)putchar('-');x=abs(x);print(x);putchar('\n');}
il void write(ll x){if(x<0)putchar('-');x=abs(x);print(x);putchar(' ');}
using namespace std;
#define N 100010
ll f[N],a[N],b[N];
bool vis[N];
int main(){
ll n=0,m=0;
while(scanf("%d",&a[++n])==1);n--;
for(ll i=n;i;i--){
f[i]=1;
for(ll j=i+1;j<=n;j++){
if(a[i]>=a[j]&&f[j]+1>f[i])f[i]=f[j]+1;
}
m=max(m,f[i]);
}
writeln(m);m=1;b[1]=a[1];
for(ll i=2;i<=n;i++){
ll pd=0;
sort(b,b+m+1);
for(ll j=1;j<=m;j++){
if(a[i]<=b[j]){b[j]=a[i];pd=1;break;}
}
if(!pd)b[++m]=a[i];
}
writeln(m);
return 0;
}

#### 2.O(nlogn)做法

#include <cstdio>
#include <cstring>
#define ll int
#define inf 1<<30
#define il inline
il ll max(ll x,ll y){return x>y?x:y;}
il ll min(ll x,ll y){return x<y?x:y;}
il ll abs(ll x){return x>0?x:-x;}
il void swap(ll &x,ll &y){ll t=x;x=y;y=t;}
x=0;ll f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-f;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
x*=f;
}
il void print(ll x){if(x<0)putchar('-');x=abs(x);if(x>9)print(x/10);putchar(x%10+'0');}
il void writeln(ll x){if(x<0)putchar('-');x=abs(x);print(x);putchar('\n');}
il void write(ll x){if(x<0)putchar('-');x=abs(x);print(x);putchar(' ');}
using namespace std;
#define N 100010
ll a[N],f[N],n,m;
int main(){
while(scanf("%d",&a[++n])==1);
n--;m=1;
memset(f,127,sizeof(f));
f[1]=a[1];
for(ll i=2;i<=n;i++){
if(f[m]>=a[i])f[++m]=a[i];
else {
ll l=0,r=m;
while(l<r){
ll mid=(l+r)>>1;
if(f[mid]>=a[i])l=mid+1;
else r=mid;
}
f[l]=a[i];
}
}
writeln(m);m=1;
memset(f,-1,sizeof(f));f[1]=a[1];
for(ll i=2;i<=n;i++){
if(f[m]<a[i])f[++m]=a[i];
else {
ll l=0,r=m;
while(l<r){
ll mid=(l+r)>>1;
if(f[mid]>=a[i])r=mid;
else l=mid+1;
}
f[l]=a[i];
}
}
writeln(m);
return 0;
}

## 3.尼克的任务

#include <cstdio>
#include <cstring>
#define ll int
#define inf 1<<30
#define il inline
il ll max(ll x,ll y){return x>y?x:y;}
il ll min(ll x,ll y){return x<y?x:y;}
il ll abs(ll x){return x>0?x:-x;}
il void swap(ll &x,ll &y){ll t=x;x=y;y=t;}
x=0;ll f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-f;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
x*=f;
}
il void print(ll x){if(x<0)putchar('-');x=abs(x);if(x>9)print(x/10);putchar(x%10+'0');}
il void writeln(ll x){if(x<0)putchar('-');x=abs(x);print(x);putchar('\n');}
il void write(ll x){if(x<0)putchar('-');x=abs(x);print(x);putchar(' ');}
using namespace std;
#define N 100100
ll n,k,f[N],sum[N];
struct node{ll p,t;}t[N];
bool cmp(node a,node b){return a.p>b.p;}
int main(){
for(ll i=n;i;i--){
if(sum[i]==0)f[i]=f[i+1]+1;
else {
for(ll j=1;j<=k;j++){
if(t[j].p==i)f[i]=max(f[i],f[i+t[j].t]);
}
}
}
writeln(f[1]);
return 0;
}

## 4.丝绸之路

$f[i][j]=min(f[i][j-1],f[i-1][j-1]+d[i]*c[j])$

#include <cstdio>
#include <cstring>
#define ll int
#define inf 1<<30
#define il inline
il ll max(ll x,ll y){return x>y?x:y;}
il ll min(ll x,ll y){return x<y?x:y;}
il ll abs(ll x){return x>0?x:-x;}
il void swap(ll &x,ll &y){ll t=x;x=y;y=t;}
x=0;ll f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-f;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
x*=f;
}
il void print(ll x){if(x<0)putchar('-');x=abs(x);if(x>9)print(x/10);putchar(x%10+'0');}
il void writeln(ll x){if(x<0)putchar('-');x=abs(x);print(x);putchar('\n');}
il void write(ll x){if(x<0)putchar('-');x=abs(x);print(x);putchar(' ');}
using namespace std;
#define N 1010
ll f[N][N],d[N],c[N],n,m;
//f[i][j]表示第j天在第i个城市的最小疲劳值
int main(){
for(ll i=1;i<=n;i++){
f[i][i]=f[i-1][i-1]+c[i]*d[i];
for(ll j=i+1;j<=m;j++){
f[i][j]=min(f[i][j-1],f[i-1][j-1]+d[i]*c[j]);
}
}
writeln(f[n][m]);
return 0;
}

## 5.分队问题

4

2 3 3 3

f[i]

#include <cstdio>
#include <cstring>
#include <algorithm>
#define ll int
#define inf 1<<30
#define il inline
il ll max(ll x,ll y){return x>y?x:y;}
il ll min(ll x,ll y){return x<y?x:y;}
il ll abs(ll x){return x>0?x:-x;}
il void swap(ll &x,ll &y){ll t=x;x=y;y=t;}
x=0;ll f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-f;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
x*=f;
}
il void print(ll x){if(x<0)putchar('-');x=abs(x);if(x>9)print(x/10);putchar(x%10+'0');}
il void writeln(ll x){if(x<0)putchar('-');x=abs(x);print(x);putchar('\n');}
il void write(ll x){if(x<0)putchar('-');x=abs(x);print(x);putchar(' ');}
using namespace std;
#define N 1000100
ll n,a[N],f[N],g[N];
int main(){
sort(a+1,a+n+1);
for(ll i=1;i<=n;i++){
if(i>=a[i])f[i]=g[i-a[i]]+1;
g[i]=max(f[i],g[i-1]);
}
writeln(f[n]);
return 0;
}

## 6.低价购买

#include <cstdio>
#include <cstring>
#define ll int
#define inf 1<<30
#define il inline
il ll max(ll x,ll y){return x>y?x:y;}
il ll min(ll x,ll y){return x<y?x:y;}
il ll abs(ll x){return x>0?x:-x;}
il void swap(ll &x,ll &y){ll t=x;x=y;y=t;}
x=0;ll f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-f;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
x*=f;
}
il void print(ll x){if(x<0)putchar('-');x=abs(x);if(x>9)print(x/10);putchar(x%10+'0');}
il void writeln(ll x){if(x<0)putchar('-');x=abs(x);print(x);putchar('\n');}
il void write(ll x){if(x<0)putchar('-');x=abs(x);print(x);putchar(' ');}
using namespace std;
#define N 5010
ll a[N],f[N],n,dp[N];
int main(){
for(ll i=1;i<=n;i++){
f[i]=1;
for(ll j=1;j<i;j++){
if(a[i]<a[j])f[i]=max(f[i],f[j]+1);
}
ans1=max(f[i],ans1);
}
ll ans2=0;
for(ll i=1;i<=n;i++){
if(f[i]==1)dp[i]=1;
for(ll j=1;j<i;j++){
if(f[i]==f[j]+1&&a[i]<a[j])dp[i]+=dp[j];
else if(f[i]==f[j]&&a[i]==a[j])dp[i]=0;
}
if(f[i]==ans1)ans2+=dp[i];
}
write(ans1);writeln(ans2);
return 0;
}

## 7.回文字串

get了一个很巧妙的解法：

$if(s1[i]==s2[j])f[i][j]=f[i-1][j-1]+1$

$f[i][j]=max(f[i-1][j],f[i][j-1])$

#include <cstdio>
#include <cstring>
#define ll int
#define inf 1<<30
#define il inline
il ll max(ll x,ll y){return x>y?x:y;}
il ll min(ll x,ll y){return x<y?x:y;}
il ll abs(ll x){return x>0?x:-x;}
il void swap(ll &x,ll &y){ll t=x;x=y;y=t;}
x=0;ll f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-f;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
x*=f;
}
il void print(ll x){if(x<0)putchar('-');x=abs(x);if(x>9)print(x/10);putchar(x%10+'0');}
il void writeln(ll x){if(x<0)putchar('-');x=abs(x);print(x);putchar('\n');}
il void write(ll x){if(x<0)putchar('-');x=abs(x);print(x);putchar(' ');}
using namespace std;
#define N 1010
char s1[N],s2[N];
ll f[N][N],n;
int main(){
scanf("%s",s1+1);n=strlen(s1+1);
for(ll i=1;i<=n;i++)s2[n-i+1]=s1[i];
for(ll i=1;i<=n;i++){
for(ll j=1;j<=n;j++){
if(s1[i]==s2[j])f[i][j]=f[i-1][j-1]+1;
else f[i][j]=max(f[i-1][j],f[i][j-1]);
}
}
writeln(n-f[n][n]);
return 0;
}

## 8.[模板]最长公共子序列

5
3 2 1 4 5
1 2 3 4 5

#include <cstdio>
#include <cstring>
#define ll int
#define inf 1<<30
#define il inline
il ll max(ll x,ll y){return x>y?x:y;}
il ll min(ll x,ll y){return x<y?x:y;}
il ll abs(ll x){return x>0?x:-x;}
il void swap(ll &x,ll &y){ll t=x;x=y;y=t;}
x=0;ll f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-f;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
x*=f;
}
il void print(ll x){if(x<0)putchar('-');x=abs(x);if(x>9)print(x/10);putchar(x%10+'0');}
il void writeln(ll x){if(x<0)putchar('-');x=abs(x);print(x);putchar('\n');}
il void write(ll x){if(x<0)putchar('-');x=abs(x);print(x);putchar(' ');}
using namespace std;
#define N 100010
ll n,a1[N],a2[N],f[N],map[N];
int main(){
memset(f,127,sizeof(f));
f[0]=0;ll m=0;
for(ll i=1;i<=n;i++){
if(a2[i]>f[m])f[++m]=a2[i];
else {
ll l=0,r=m;
while(l<r){
ll mid=(l+r)>>1;
if(f[mid]>=a2[i])r=mid;
else l=mid+1;
}
f[l]=a2[i];
}
}
writeln(m);
return 0;
}
[模板]最长公共子序列

## 9.魔族密码

#include <cstdio>
#include <cstring>
#include <algorithm>
#define ll int
#define inf 1<<30
#define il inline
il ll max(ll x,ll y){return x>y?x:y;}
il ll min(ll x,ll y){return x<y?x:y;}
il ll abs(ll x){return x>0?x:-x;}
il void swap(ll &x,ll &y){ll t=x;x=y;y=t;}
x=0;ll f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-f;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
x*=f;
}
il void print(ll x){if(x<0)putchar('-');x=abs(x);if(x>9)print(x/10);putchar(x%10+'0');}
il void writeln(ll x){if(x<0)putchar('-');x=abs(x);print(x);putchar('\n');}
il void write(ll x){if(x<0)putchar('-');x=abs(x);print(x);putchar(' ');}
using namespace std;
#define N 2010
ll n,f[N],ans=0;
struct node{char ch[76];ll len;}a[N];
#define base 233
#define mod 19260817
#define ull unsigned long long
ull h[N][76];
bool cmp(node a,node b){return a.len<b.len;}
int main(){
memset(h,0,sizeof(h));
for(ll i=1;i<=n;i++){
scanf("%s",a[i].ch+1);
a[i].len=strlen(a[i].ch+1);
f[i]=1;
}
sort(a+1,a+n+1,cmp);
for(ll i=1;i<=n;i++)
for(ll j=1;j<=a[i].len;j++)
h[i][j]=(h[i][j-1]*base+(ull)(a[i].ch[j]))%mod;
for(ll i=1;i<=n;i++){
for(ll j=1;j<i;j++){
if(a[i].ch[1]!=a[j].ch[1])continue;
if(h[i][a[j].len]==h[j][a[j].len])f[i]=max(f[i],f[j]+1);
}
ans=max(ans,f[i]);
}
writeln(ans);
return 0;
}

## 10.创意吃鱼法

题目链接

f[i][j]=min(f[i-1][j-1],min(l[i-1][j],r[i][j-1]))+1(a[i][j]==1)

#include <cstdio>
#include <cstring>
#define ll int
#define inf 1<<30
#define il inline
il ll max(ll x,ll y){return x>y?x:y;}
il ll min(ll x,ll y){return x<y?x:y;}
il ll abs(ll x){return x>0?x:-x;}
il void swap(ll &x,ll &y){ll t=x;x=y;y=t;}
x=0;ll f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-f;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
x*=f;
}
il void print(ll x){if(x<0)putchar('-');x=abs(x);if(x>9)print(x/10);putchar(x%10+'0');}
il void writeln(ll x){if(x<0)putchar('-');x=abs(x);print(x);putchar('\n');}
il void write(ll x){if(x<0)putchar('-');x=abs(x);print(x);putchar(' ');}
using namespace std;
#define N 2600
ll n,m,a[N][N],f[N][N],ans=0,l[N][N],r[N][N];
int main(){
for(ll i=1;i<=n;i++){
for(ll j=1;j<=m;j++){
if(!a[i][j])l[i][j]=l[i-1][j]+1,r[i][j]=r[i][j-1]+1;
else f[i][j]=min(f[i-1][j-1],min(l[i-1][j],r[i][j-1]))+1;
ans=max(ans,f[i][j]);
}
}
memset(f,0,sizeof(f));
memset(l,0,sizeof(l));
memset(r,0,sizeof(r));
for(ll i=1;i<=n;i++){
for(ll j=m;j;j--){
if(!a[i][j])l[i][j]=l[i-1][j]+1,r[i][j]=r[i][j+1]+1;
else f[i][j]=min(f[i-1][j+1],min(l[i-1][j],r[i][j+1]))+1;
ans=max(ans,f[i][j]);
}
}
writeln(ans);
return 0;
}

#include <cstdio>
#include <cmath>
#include <cstring>
#define ll int
#define inf 1<<30
#define il inline
il ll max(ll x,ll y){return x>y?x:y;}
il ll min(ll x,ll y){return x<y?x:y;}
il ll abs(ll x){return x>0?x:-x;}
il void swap(ll &x,ll &y){ll t=x;x=y;y=t;}
x=0;ll f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-f;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
x*=f;
}
il void print(ll x){if(x<0)putchar('-');x=abs(x);if(x>9)print(x/10);putchar(x%10+'0');}
il void writeln(ll x){if(x<0)putchar('-');x=abs(x);print(x);putchar('\n');}
il void write(ll x){if(x<0)putchar('-');x=abs(x);print(x);putchar(' ');}
using namespace std;
#define N 110
ll a[N][N],f[N][N],n,mx=0,m;
int main(){
for(ll i=1;i<=n;i++){
for(ll j=1;j<=m;j++){
if(a[i][j]==1)f[i][j]=min(min(f[i-1][j-1],f[i-1][j]),f[i][j-1])+1;
mx=max(f[i][j],mx);
}
}
writeln(mx);
}

## 11.UVA10635 Prince and Princess

#include <cstdio>
#include <cstring>
#define ll long long
#define inf 1<<30
#define il inline
#define in2(a,b) in1(a),in1(b)
#define in3(a,b,c) in2(a,b),in1(c)
#define in4(a,b,c,d) in2(a,b),in2(c,d)
il int max(int x,int y){return x>y?x:y;}
il int min(int x,int y){return x<y?x:y;}
il int abs(int x){return x>0?x:-x;}
il void swap(int &x,int &y){int t=x;x=y;y=t;}
x=0;ll f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-f;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
x*=f;
}
x=0;int f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-f;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
x*=f;
}
using namespace std;
#define N 100010
int a[N],p[N],q[N],n,l1,l2,f[N];
int main(){
int t;in1(t);
for(int k=1;k<=t;k++){
memset(f,127,sizeof(f));
in3(n,l1,l2);
for(int i=1;i<=l1+1;i++){int x;in1(x);p[x]=i;}
for(int i=1;i<=l2+1;i++){int x;in1(x);q[i]=p[x];}
int m=1;f[1]=q[1];
for(int i=1;i<=l2+1;i++){
if(q[i]==0)continue;
if(q[i]>f[m])f[++m]=q[i];
else {
int l=1,r=m;
while(l<r){
int mid=(l+r)>>1;
if(f[mid]>q[i])r=mid;
else l=mid+1;
}
f[l]=q[i];
}
}
printf("Case %d: %d\n",k,m);
}
return 0;
}
UVA10635

## 12.木棍加工

Dilworth定理的大概意思：最少的下降序列个数就等于整个序列最长上升子序列的长度

#include <cstdio>
#include <cstring>
#include <algorithm>
#define ll long long
#define inf 1<<30
#define il inline
#define in2(a,b) in1(a),in1(b)
#define in3(a,b,c) in2(a,b),in1(c)
#define in4(a,b,c,d) in2(a,b),in2(c,d)
il int max(int x,int y){return x>y?x:y;}
il int min(int x,int y){return x<y?x:y;}
il int abs(int x){return x>0?x:-x;}
il void swap(int &x,int &y){int t=x;x=y;y=t;}
x=0;ll f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-f;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
x*=f;
}
x=0;int f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-f;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
x*=f;
}
using namespace std;
#define N 5010
int n,f[N];
struct node{int w,l;}a[N];
bool cmp(node a,node b){
if(a.w!=b.w)return a.w>b.w;
else return a.l>b.l;
}
int main(){
in1(n);int mx=0;
for(int i=1;i<=n;i++)in2(a[i].l,a[i].w);
sort(a+1,a+n+1,cmp);
for(int i=1;i<=n;i++){
f[i]=1;
for(int j=1;j<i;j++){
if(a[i].l>a[j].l)f[i]=max(f[i],f[j]+1);
}
mx=max(f[i],mx);
}
printf("%d\n",mx);
return 0;
}

## 13.[USACO08MAR]跨河River Crossing

#include <cstdio>
#include <cstring>
#define ll long long
#define inf 1<<30
#define il inline
#define in2(a,b) in1(a),in1(b)
#define in3(a,b,c) in2(a,b),in1(c)
#define in4(a,b,c,d) in2(a,b),in2(c,d)
il int max(int x,int y){return x>y?x:y;}
il int min(int x,int y){return x<y?x:y;}
il int abs(int x){return x>0?x:-x;}
il void swap(int &x,int &y){int t=x;x=y;y=t;}
x=0;ll f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-f;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
x*=f;
}
x=0;int f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-f;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
x*=f;
}
using namespace std;
#define N 3010
int a[N],c[N],n,m,f[N];
//fi送i头牛过河最小花费
int main(){
in2(n,m);
for(int i=1;i<=n;i++)in1(a[i]);
c[0]=2*m;
for(int i=1;i<=n;i++)c[i]=c[i-1]+a[i];
for(int i=1;i<=n;i++){
f[i]=c[i];
for(int j=1;j<i;j++){
f[i]=min(f[i],f[j]+c[i-j]);
}
}
printf("%d\n",f[n]-m);
return 0;
}
[USACO08MAR]跨河River Crossing

## 14.UVA11400 Lighting System Design

#include <cstdio>
#include <cstring>
#include <algorithm>
#define ll long long
#define inf 1<<30
#define il inline
#define in2(a,b) in1(a),in1(b)
#define in3(a,b,c) in2(a,b),in1(c)
#define in4(a,b,c,d) in2(a,b),in2(c,d)
il int max(int x,int y){return x>y?x:y;}
il int min(int x,int y){return x<y?x:y;}
il int abs(int x){return x>0?x:-x;}
il void swap(int &x,int &y){int t=x;x=y;y=t;}
x=0;ll f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-f;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
x*=f;
}
x=0;int f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-f;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
x*=f;
}
using namespace std;
#define N 1010
int n,f[N],c[N];
//前i种灯的最优价值
struct node{int v,k,c,l;}a[N];
bool cmp(node a,node b){return a.v<b.v;}
int main(){
while(scanf("%d",&n)==1&&n){
for(int i=1;i<=n;i++){
in4(a[i].v,a[i].k,a[i].c,a[i].l);
}
sort(a+1,a+n+1,cmp);
for(int i=1;i<=n;i++)c[i]=c[i-1]+a[i].l;
for(int i=1;i<=n;i++){
f[i]=a[i].k+a[i].c*c[i];
for(int j=1;j<i;j++){
f[i]=min(f[i],f[j]+(c[i]-c[j])*a[i].c+a[i].k);
}
}
printf("%d\n",f[n]);
}
return 0;
}
uva11400

## 15.出租车拼车

$f[i][j]=min(f[i-1][j-x]+x*t[i]+d) (1≤x≤min(z[i],j))$

$f[i][j]=f[i-1][j] (x=0)$即如果没有人上车，就不需要付 d 元

#include <cstdio>
#include <cstring>
#include <algorithm>
#define ll int
#define inf 1<<30
#define il inline
#define in2(a,b) in1(a);in1(b)
#define in3(a,b,c) in2(a,b);in1(c)
#define in4(a,b,c,d) in2(a,b);in2(c,d)
il ll max(ll x,ll y){return x>y?x:y;}
il ll min(ll x,ll y){return x<y?x:y;}
il ll abs(ll x){return x>0?x:-x;}
il void swap(ll &x,ll &y){ll t=x;x=y;y=t;}
x=0;ll f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-f;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
x*=f;
}
using namespace std;
#define N 500
int f[N][N],t[N],z[N];
//前i辆车载j个oier
int n,k,d,s;
int main(){
in4(n,k,d,s);ll sum=0;
for(ll i=1;i<=k;i++){in2(t[i],z[i]);sum+=z[i];}
if(sum<n){printf("impossible\n");return 0;}
for(ll i=1;i<=n;i++)f[0][i]=inf;
for(ll i=1;i<=k;i++){
for(ll j=1;j<=n;j++){
f[i][j]=inf;
for(ll k=0;k<=min(z[i],j);k++){
if(k==0)f[i][j]=f[i-1][j];
else f[i][j]=min(f[i][j],f[i-1][j-k]+t[i]*k+d);
}
}
}
printf("%d\n",f[k][n]);
return 0;
}

15道题搞完啦，现在也已经暑假了，更新速度就会比较快啦

## 16.最佳课题选择

#include <cstdio>
#define ll long long
#define inf 1<<30
#define il inline
#define in2(a,b) in1(a),in1(b)
#define in3(a,b,c) in2(a,b),in1(c)
#define in4(a,b,c,d) in2(a,b),in2(c,d)
il int max(int x,int y){return x>y?x:y;}
il ll min(ll x,ll y){return x<y?x:y;}
il int abs(int x){return x>0?x:-x;}
il void swap(int &x,int &y){int t=x;x=y;y=t;}
x=0;ll f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-f;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
x*=f;
}
x=0;int f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-f;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
x*=f;
}
using namespace std;
#define N 500
ll n,m;
ll a[N],b[N],f[N][N];
//前i个课题拿来写j篇论文
ll power(ll a,ll b){
ll ans=1,base=a;
while(b){
if(b&1)ans*=base;
base*=base;
b>>=1;
}
return ans;
}
int main(){
in2(n,m);
for(ll i=1;i<=m;i++){
in2(a[i],b[i]);
}
for(ll i=1;i<=n;i++)f[0][i]=inf;
for(ll i=1;i<=m;i++){
for(ll j=1;j<=n;j++){
f[i][j]=inf;
for(ll k=0;k<=j;k++){
f[i][j]=min(f[i][j],f[i-1][j-k]+a[i]*power(k,b[i]));
}
}
}
printf("%lld\n",f[m][n]);
return 0;
}

## 17.[USACO06FEB]奶牛零食Treats for the Cows

#include <cstdio>
using namespace std;
int n,a[2010];
int f[2010][2010];
int max(int x,int y){return x>y?x:y;}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=1;i<=n;i++)f[i][i]=a[i]*n;
for(int len=2;len<=n;len++){
for(int l=1;l<=n;l++){
int r=len+l-1;
if(r>n)continue;
f[l][r]=max(f[l][r-1]+a[r]*(n-len+1),f[l+1][r]+a[l]*(n-len+1));
}
}
printf("%d",f[1][n]);
return 0;
}

## 18.能量项链

#include <cstdio>
using namespace std;
int n,f[210][210],a[210],mx=0;
int max(int x,int y){return x>y?x:y;}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",&a[i]),a[i+n]=a[i];
for(int i=2*n;i>=1;i--)
for(int j=i+1;j<=2*n;j++)
for(int k=i;k<j;k++)
f[i][j]=max(f[i][j],f[i][k]+f[k+1][j]+a[i]*a[k+1]*a[j+1]);
for(int i=1;i<=2*n;i++){
mx=max(f[i][i+n-1],mx);
}
printf("%d\n",mx);
return 0;
}

## 20.摆花

#include <cstdio>
#define mod 1000007
using namespace std;
//f[i,j]表示第i种花一共选了j盆
int f[1000][1000],a[1000],n,m;
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
f[0][0]=1;
for(int i=1;i<=n;i++){
for(int j=0;j<=m;j++){
for(int k=0;k<=a[i];k++){
if(j-k>=0)f[i][j]=(f[i][j]+f[i-1][j-k])%mod;
}
}
}
printf("%d\n",f[n][m]%mod);
return 0;
} 

## 21.HDU5115

$f[l][r]=min(f[l][r],f[l][k-1]+f[k+1][r]+a[k]+b[l-1]+b[r+1])$（设k为我们在杀死l到r头狼时最后杀死的那头狼）

#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
#define ll long long
#define N 500
#define inf (1<<30)
ll f[N][N];
ll n,a[N],b[N];
int main(){
int t,kase=0;scanf("%d",&t);
while(t--){
scanf("%lld",&n);
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(i<=j)f[i][j]=inf;
else f[i][j]=0;
}
}
for(int i=1;i<=n;i++)
scanf("%lld",&a[i]);
for(int i=1;i<=n;i++)
scanf("%lld",&b[i]);
for(int i=1;i<=n;i++)
f[i][i]=a[i]+b[i-1]+b[i+1];
for(int len=1;len<=n;len++){
for(int l=1;l+len<=n;l++){
int r=l+len;
for(int k=l;k<=r;k++){
f[l][r]=min(f[l][r],f[l][k-1]+f[k+1][r]+a[k]+b[l-1]+b[r+1]);
}
}
}
printf("Case #%d: %lld\n",++kase,f[1][n]);
}
return 0;
} 
HDU5115

## 22.[USACO13NOV]POGO的牛Pogo-Cow

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
struct node {int val,x;}a[2000];
bool cmp(node a,node b){
return a.x<b.x;
}
int f[2000][2000];
//f[i,j]表示最后跳的两个点是i和j
int main(){
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d%d",&a[i].x,&a[i].val);
}
sort(a+1,a+n+1,cmp);
for(int i=1;i<=n;i++){
for(int j=i+1;j<=n;j++){
f[i][j]=a[i].val+a[j].val;
}
}
for(int i=1;i<=n;i++){
for(int j=i-1;j;j--){
for(int k=j-1;k;k--){
if(a[j].x-a[k].x>a[i].x-a[j].x)continue;
f[j][i]=max(f[j][i],f[k][j]+a[i].val);
}
}
}
int ans=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
ans=max(f[i][j],ans);
}
}
memset(f,0,sizeof(f));
for(int i=1;i<=n;i++){
for(int j=i+1;j<=n;j++){
f[i][j]=a[i].val+a[j].val;
}
}
for(int i=n;i;i--){
for(int j=i+1;j<=n;j++){
for(int k=j+1;k<=n;k++){
if(a[k].x-a[j].x>a[j].x-a[i].x)continue;
f[i][j]=max(f[i][j],f[j][k]+a[i].val);
}
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
ans=max(f[i][j],ans);
}
}
printf("%d\n",ans);
return 0;
} 
n^3
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
struct node {int val,x;}a[2000];
bool cmp(node a,node b){
return a.x<b.x;
}
int f[2000][2000];
//f[i,j]最后从j点跳到i点
int main(){
int n,ans=0;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d%d",&a[i].x,&a[i].val);
}
sort(a+1,a+n+1,cmp);
for(int j=1;j<=n;j++){
int k=j-1,val=f[j][0]+a[j].val;
for(int i=j+1;i<=n;i++){
while(k&&a[i].x-a[j].x>=a[j].x-a[k].x)
val=max(val,a[j].val+f[j][k]),k--;
f[i][j]=max(f[i][j],val);
ans=max(ans,val+a[i].val);
}
}
for(int j=n;j;j--){
int k=j+1,val=f[j][n+1]+a[j].val;
for(int i=j-1;i;i--){
while(k<=n&&a[j].x-a[i].x>=a[k].x-a[j].x)
val=max(val,f[j][k]+a[j].val),k++;
f[i][j]=max(f[i][j],val);
ans=max(ans,val+a[i].val);
}
}
printf("%d\n",ans);
return 0;
} 
n^2

## 23.乌龟棋

#include <cstdio>
using namespace std;
int f[40][40][40][40],num[500],p[500];
inline int max(int x,int y){return (x)>(y)?(x):(y);}
int main(){
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)scanf("%d",&num[i]);
for(int i=1;i<=m;i++){
int x;
scanf("%d",&x);
p[x]++;
}
f[0][0][0][0]=num[1];
for(int a=0;a<=p[1];a++){
for(int b=0;b<=p[2];b++){
for(int c=0;c<=p[3];c++){
for(int d=0;d<=p[4];d++){
int to=a+b*2+c*3+d*4+1;
if(a)f[a][b][c][d]=max(f[a][b][c][d],f[a-1][b][c][d]+num[to]);
if(b)f[a][b][c][d]=max(f[a][b][c][d],f[a][b-1][c][d]+num[to]);
if(c)f[a][b][c][d]=max(f[a][b][c][d],f[a][b][c-1][d]+num[to]);
if(d)f[a][b][c][d]=max(f[a][b][c][d],f[a][b][c][d-1]+num[to]);
}
}
}
}
printf("%d\n",f[p[1]][p[2]][p[3]][p[4]]);
return 0;
} 

## 24.[USACO08JAN]跑步Running

$f[i][j]=max(f[i][j],f[i-1][j])$

$f[i+j][0]=max(f[i][j],f[i+j][0])$

$f[i+1][j+1]=max(f[i+1][j+1],f[i][j]+d[i+1])$

#include <cstdio>
#include <algorithm>
using namespace std;
int n,m,d[100000];
int f[10505][505];
//f[i,j]表示第i分钟的疲劳度为j的最优解
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&d[i]);
}
f[1][1]=d[1];
for(int i=1;i<=n;i++){
for(int j=0;j<=min(m,i);j++){
if(j==0){
f[i][j]=max(f[i-1][0],f[i][j]);
}else {
f[i+j][0]=max(f[i+j][0],f[i][j]);//选择休息
}
f[i+1][j+1]=max(f[i+1][j+1],f[i][j]+d[i+1]);//选择跑步
}
}
printf("%d\n",f[n][0]);
return 0;
}

## 25.过河

$f[i]=min(f[i-j]+flag[i])$

1.2520压缩，因为$gcd(1,10)=2520$，所以无论s,t是多少都一定可以跳到2520，所以两个石头间的距离大于2520就可以直接压掉2520的距离了

2.90压缩，这是一个利用$exgcd$推导出来的压缩方法，下面给一个证明的链接，这里就不证明了（太长），直接说结论：当两个石头的距离大于$t*(t-1)$那么就能压缩，而$t*(t-1)$的最大值是90

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int l,m,s,t;
int f[50000],a[50000],flag[50000];
int main(){
scanf("%d%d%d%d",&l,&s,&t,&m);
if(s==t){
int x,ans=0;
for(int i=1;i<=m;i++){
scanf("%d",&x);
if(!(x%s))ans++;
}
printf("%d\n",ans);
return 0;
}
for(int i=1;i<=m;i++){
scanf("%d",&a[i]);
}
int cnt=0;a[0]=0;
sort(a+1,a+m+1);
a[m+1]=min(l-a[m],100);
for(int i=1;i<=m;i++){
f[i]=min(a[i]-a[i-1],90);
cnt+=f[i];
flag[cnt]=1;
}
cnt+=a[m+1];
memset(f,127,sizeof(f));
f[0]=0;
for(int i=1;i<=cnt+9;i++){
for(int j=s;j<=t;j++){
if(i-s>=0){
f[i]=min(f[i],f[i-j]+flag[i]);
}
}
}
int ans=1<<30;
for(int i=cnt;i<=cnt+9;i++){
ans=min(ans,f[i]);
}
printf("%d\n",ans);
return 0;
} 

## 26.[USACO07FEB]牛的词汇The Cow Lexicon

$f[i]=min(f[i],f[i+len[j]+tot]+tot)$

#include <bits/stdc++.h>
using namespace std;
int f[1000],l[1000];
int w,L;
char a[1000],b[500][50];
int check(int i,int id){
int tot=0;
for(int j=1;i<=L;i++){
if(a[i]==b[id][j])j++;
else tot++;
}
return -1;
}
int main(){
scanf("%d%d",&w,&L);
scanf("%s",a+1);
for(int i=1;i<=w;i++){
scanf("%s",b[i]+1);
l[i]=strlen(b[i]+1);
}
for(int i=L;i;i--){
f[i]=f[i+1]+1;
for(int j=1;j<=w;j++){
if(a[i]==b[j][1]){
int pd=check(i,j);
if(pd!=-1){
f[i]=min(f[i],f[i+l[j]+pd]+pd);
}
}
}
}
printf("%d\n",f[1]);
return 0;
} 

## 27.[USACO07MAR]牛交通Cow Traffic

#include <bits/stdc++.h>
#define N 100010
using namespace std;
struct edge {
int to,nxt,v;
}e[N];
int in[N],q[N*10];
int x[N],y[N];
void ins(int u,int v){
e[++cnt].to=v;
}
int dp[N],f[N];
void dfs(int x){
if(!f[e[i].to])dfs(e[i].to);
f[x]+=f[e[i].to];
}
}
void dfs1(int x){
if(!dp[e[i].to])dfs1(e[i].to);
dp[x]+=dp[e[i].to];
}
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
int u,v;
scanf("%d%d",&u,&v);
if(u>v)swap(u,v);
ins(u,v);
x[i]=u;y[i]=v;
in[v]++;
}
for(int i=1;i<=n;i++){
if(!in[i])dfs1(i);
}
cnt=0;
for(int i=1;i<=m;i++){
ins(y[i],x[i]);
}
dfs(n);
int ans=0;
for(int i=1;i<=m;i++){
ans=max(ans,f[x[i]]*dp[y[i]]);
}
printf("%d\n",ans);
return 0;
} 

## 28.[USACO07NOV]挤奶的时间Milking Time

#include <bits/stdc++.h>
using namespace std;
int n,m,t;
struct node {
int l,r,val;
}a[10000];
int f[1000000];
bool cmp(node a,node b){
return a.r<b.r;
}
int main(){
scanf("%d%d%d",&n,&m,&t);
for(int i=1;i<=m;i++){
scanf("%d%d%d",&a[i].l,&a[i].r,&a[i].val);
}
int ans=0;
sort(a+1,a+m+1,cmp);
a[0].r=-1000000;
for(int i=1;i<=m;i++){
for(int j=0;j<i;j++){
if(a[i].l-a[j].r>=t)f[i]=max(f[i],f[j]+a[i].val);
}
ans=max(ans,f[i]);
}
printf("%d\n",ans);
} 

## 29.装箱问题

#include <bits/stdc++.h>
using namespace std;
int v,a[500],n,f[25500];
int main(){
scanf("%d%d",&v,&n);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
for(int i=1;i<=n;i++){
for(int j=v;j>=a[i];j--){
f[j]=max(f[j],f[j-a[i]]+a[i]);
}
}
int ans=0;
printf("%d\n",v-f[v]);
} 

## 30.[HNOI2004]打鼹鼠

#include <bits/stdc++.h>
using namespace std;
#define N 10010
int n,m,x[N],y[N],t[N];
int f[N];
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)f[i]=1;
int ans=0;
for(int i=1;i<=m;i++){
scanf("%d%d%d",&t[i],&x[i],&y[i]);
for(int j=1;j<i;j++){
if(abs(x[i]-x[j])+abs(y[i]-y[j])<=t[i]-t[j])
f[i]=max(f[i],f[j]+1);
}
ans=max(ans,f[i]);
}
printf("%d\n",ans);
}
[HNOI2004]打鼹鼠

## 31.道路游戏

NOIP2009T4，专门写了一篇博客来总结一下

WC居然有这种简单题？！

## 34.教主的花园

#include <bits/stdc++.h>
using namespace std;
#define N 100010
int n,a[N][5];
int f[N][5][5][5];
//第i个位置种了第j种树，上一个位置种的是比它大还是比它小：1小2大
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d%d%d",&a[i][1],&a[i][2],&a[i][3]);
f[1][1][2][1]=a[1][1];
f[1][2][2][2]=f[1][2][1][2]=a[1][2];
f[1][3][1][3]=a[1][3];
for(int i=2;i<=n;i++){
for(int j=1;j<=3;j++){
f[i][1][2][j]=max(f[i-1][2][1][j],f[i-1][3][1][j])+a[i][1];
f[i][2][1][j]=f[i-1][1][2][j]+a[i][2];
f[i][2][2][j]=f[i-1][3][1][j]+a[i][2];
f[i][3][1][j]=max(f[i-1][2][2][j],f[i-1][1][2][j])+a[i][3];
}
}
int ans=0;
ans=max(f[n][1][2][2],f[n][1][2][3]);
ans=max(ans,max(f[n][2][2][3],f[n][2][1][1]));
ans=max(ans,max(f[n][3][1][2],f[n][3][1][1]));
printf("%d\n",ans);
return 0;
}
View Code

## 35.烹调方案

$a[i]-b[i]*(t+c[i])+a[j]-b[j]*(t+c[i]+c[j])$//i先做
$a[j]-b[j]*(t+c[j])+a[i]-b[i]*(t+c[i]+c[j])$//j先做

$a[i]-b[i]*(t+c[i])+a[j]-b[j]*(t+c[i]+c[j])>a[j]-b[j]*(t+c[j])+a[i]-b[i]*(t+c[i]+c[j])$

$-b[i]*(t+c[i])-b[j]*(t+c[i]+c[j])>-b[j]*(t+c[j])-b[i]*(t+c[i]+c[j])$

$-b[i]*t-b[i]*c[i]-b[j]*t-b[j]*c[i]-b[j]*c[j]>-b[j]*t-b[j]*c[j]-b[i]*t-b[i]*c[i]-b[i]*c[j]$

$-b[j]*c[i]>-b[i]*c[j]$

#include <bits/stdc++.h>
using namespace std;
#define ll long long
ll n,t;
struct node {
ll a,b,c;
}a[100];
ll f[100000];
bool cmp(node i,node j){
return -j.b*i.c>-i.b*j.c;
}
int main(){
long long ans=0;
scanf("%lld%lld",&t,&n);
for(int i=1;i<=n;i++)scanf("%lld",&a[i].a);
for(int i=1;i<=n;i++)scanf("%lld",&a[i].b);
for(int i=1;i<=n;i++)scanf("%lld",&a[i].c);
sort(a+1,a+n+1,cmp);
for(int i=1;i<=n;i++){
for(int j=t;j>=a[i].c;j--){
f[j]=max(f[j],f[j-a[i].c]+a[i].a-a[i].b*j);
ans=max(ans,f[j]);
}
}
printf("%lld\n",ans);
return 0;
}

## 36.经营与开发

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define N 100010
int n,k,c,w;
double f[N];
int type[N],a[N];
int main(){
scanf("%d%d%d%d",&n,&k,&c,&w);
for(int i=1;i<=n;i++)scanf("%d%d",&type[i],&a[i]);
for(int i=n;i;i--){
if(type[i]==1)f[i]=max(f[i+1],a[i]+f[i+1]*(1-0.01*k));
else f[i]=max(f[i+1],f[i+1]*(1+0.01*c)-a[i]);
}
printf("%.2lf\n",f[1]*w);
}

## 37.货币系统

#include <bits/stdc++.h>
using namespace std;
int n,m,a[50];
long long dp[10010];
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
dp[0]=1;
for(int i=1;i<=n;i++){
for(int j=a[i];j<=m;j++){
dp[j]+=dp[j-a[i]];
}
}
printf("%lld\n",dp[m]);
}

## 38.[HAOI2012]音量调节

#include <bits/stdc++.h>
using namespace std;
int n,beginl,Max,c[2000];
bool f[2100][2010];
int main(){
scanf("%d%d%d",&n,&beginl,&Max);
for(int i=1;i<=n;i++){
scanf("%d",&c[i]);
}
f[0][beginl]=1;
for(int i=1;i<=n;i++){
for(int j=0;j<=Max;j++){
if(f[i-1][j])f[i][j+c[i]]=1;
if(f[i-1][j]&&j-c[i]>=0)f[i][j-c[i]]=1;
}
}
int ans=-1;
for(int i=Max;i;i--){
if(ans!=-1)break;
if(f[n][i])ans=i;
}
printf("%d\n",ans);
return 0;
} 

## 39.机器分配

#include <bits/stdc++.h>
using namespace std;
int n,m;
int f[100][100];
//f[i,j]表示前i个公司分配了j台机器
int a[100][100];
void print(int x,int y){
for(int i=y;i>=0;i--){
if(a[x][i]+f[x-1][y-i]==f[x][y]){
print(x-1,y-i);
printf("%d %d\n",x,i);
break;
}
}
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++)
scanf("%d",&a[i][j]);
}
f[1][1]=a[1][1];
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
for(int k=0;k<=j;k++){
f[i][j]=max(f[i][j],f[i-1][j-k]+a[i][k]);
}
}
}
printf("%d\n",f[n][m]);
print(n,m);
return 0;
} 

## 40.花店橱窗布置

#include <bits/stdc++.h>
using namespace std;
int n,m;
int f[110][110];
#define inf 0x3f3f3f3f
//f[i,j]表示第i个花瓶放第j种花的最优解
int a[110][110];
void print(int x,int val){
if(!x)return;
int i=x;
while(f[i][x]!=val)i++;
print(x-1,val-a[x][i]);
printf("%d ",i);
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
scanf("%d",&a[i][j]);
f[j][i]=-inf;
}
}
for(int i=1;i<=m;i++)f[0][i]=-inf;
f[0][0]=0;
for(int i=1;i<=m;i++){
for(int j=1;j<=min(n,i);j++){
f[i][j]=max(f[i-1][j],f[i-1][j-1]+a[j][i]);
}
}
printf("%d\n",f[m][n]);
print(n,f[m][n]);
return 0;
} 

## 41.看球泡妹子

$f[i][j][k]$表示前i场比赛一共看了j场，精彩度为k的最优解

$f[i][j][k]=max(f[i-1][j][k],f[i][j][k])$

$f[i][j][k]=max(f[i][j][k],f[i-1][j-1][k-w[i]]+v[i])$

#include <bits/stdc++.h>
using namespace std;
int n,m,k,c;
int f[110][110][2020];
//f[i][j][k]表示前i场比赛一共看了j场，精彩度为k的最优解
int a[1000],b[1000],w[1000],v[1000];
int main(){
int sum=0;
scanf("%d%d%d%d",&n,&m,&k,&c);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
for(int i=1;i<=n;i++){
scanf("%d",&b[i]);
}
for(int i=1;i<=m;i++){
int x,y;
scanf("%d%d",&x,&y);
w[i]=b[x]+b[y];
v[i]=a[x]*a[y];
sum+=w[i];
}
int ans=0;
for(int j=1;j<=k;j++){
for(int i=1;i<=m;i++){
for(int k=sum;k>=0;k--){
f[i][j][k]=max(f[i-1][j][k],f[i][j][k]);
if(k>=w[i]&&(k==w[i]||f[i-1][j-1][k-w[i]]>0))f[i][j][k]=max(f[i][j][k],f[i-1][j-1][k-w[i]]+v[i]);
if(k>=c)ans=max(f[i][j][k],ans);
}
}
}
printf("%d\n",ans<=0?-1:ans);
} 

## 42.选学霸

#include <bits/stdc++.h>
using namespace std;
#define N 20010
int n,m,k;
int f[N],cnt[N];
int tot,a[N];
bool dp[N];
int find(int x){
return f[x]==x?x:f[x]=find(f[x]);
}
int main(){
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=n;i++)f[i]=i;
for(int i=1;i<=k;i++){
int x,y;
scanf("%d%d",&x,&y);
int u=find(x),v=find(y);
f[v]=u;
}
for(int i=1;i<=n;i++)f[i]=find(f[i]);
for(int i=1;i<=n;i++){
cnt[f[i]]++;
}
int tot=0;
for(int i=1;i<=n;i++){
if(cnt[i]){
a[++tot]=cnt[i];
}
}
dp[0]=1;
for(int i=1;i<=tot;i++){
for(int j=n;j>=a[i];j--){
if(dp[j-a[i]])dp[j]=1;
}
}
int ans=0;
for(int i=1;i<=n;i++){
if(dp[i]&&abs(ans-m)>abs(i-m))ans=i;
}
printf("%d\n",ans);
}

## 43.字串距离

#include <bits/stdc++.h>
using namespace std;
char a[2000],b[2000];
int f[2000][2000],k,n,m;
//f[i][j]表示选了a串前i个字符 和b串前j个字符的最优解
int main(){
scanf("%s%s",a+1,b+1);
scanf("%d",&k);
n=strlen(a+1);m=strlen(b+1);
for(int i=1;i<=n;i++)f[i][0]=i*k;
for(int j=1;j<=m;j++)f[0][j]=j*k;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
f[i][j]=0x3f3f3f3f;
f[i][j]=min(f[i][j],f[i-1][j-1]+abs(a[i]-b[j]));
f[i][j]=min(f[i][j],min(f[i-1][j]+k,f[i][j-1]+k));
}
}
printf("%d\n",f[n][m]);
}

## 44.传球游戏

#include <bits/stdc++.h>
using namespace std;
int f[100][100];
//传到第i个人，是第j次传
int main(){
int n,m;
scanf("%d%d",&n,&m);
f[1][0]=1;
for(int j=1;j<=m;j++){
for(int i=1;i<=n;i++){
f[i][j]=f[(i==n?1:i+1)][j-1]+f[(i==1?n:i-1)][j-1];
}
}
printf("%d\n",f[1][m]);
return 0;
}

## 45.积木城堡

#include <bits/stdc++.h>
using namespace std;
int cnt[10000],f[10000],a[1000];
int x,sum,tot,n,m=0;
int main(){
scanf("%d",&n);
for(int kase=1;kase<=n;kase++){
memset(f,0,sizeof(f));
memset(a,0,sizeof(a));
sum=tot=0;
f[0]=1;
while(scanf("%d",&a[++tot])&&a[tot]!=-1)sum+=a[tot];
tot--;m=max(m,sum);
for(int i=1;i<=tot;i++){
for(int j=sum;j>=a[i];j--){
if(f[j-a[i]]&&!f[j]){
f[j]=1;cnt[j]++;
}
}
}
}
for(int i=m;i;i--){
if(cnt[i]==n){
printf("%d\n",i);
return 0;
}
}
return puts("0"),0;
}

## 47.UVA1025 A Spy in the Metro

$train[t][i][0]$表示这个时刻有没有向右的车，$train[t][i][1]$同理，表示向左

k表示时间，i表示车站，注意要倒序枚举时间

$f[k][i]=f[k+1][i]+1$

$f[k][i]=min(f[k+t[i]][i+1],f[k][i])$

$f[k][i]=min(f[k+t[i-1]][i-1],f[k][i])$

#include <bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
int f[300][60],t[100],T;
//时刻t在i车站的最优解
bool train[399][100][2];
//0向右，1向左
int main(){
int n,kase=0;
while(scanf("%d",&n)==1&&n){
memset(train,0,sizeof(train));
memset(f,0,sizeof(f));
memset(t,0,sizeof(t));
scanf("%d",&T);
for(int i=1;i<n;i++)scanf("%d",&t[i]);
int m1,m2;
scanf("%d",&m1);
for(int i=1;i<=m1;i++){
int x;
scanf("%d",&x);
for(int j=1;j<=n;j++){
train[x][j][0]=1;
x+=t[j];
}
}
scanf("%d",&m2);
for(int i=1;i<=m2;i++){
int x;
scanf("%d",&x);
for(int j=n;j>=1;j--){
train[x][j][1]=1;
x+=t[j-1];
}
}
for(int i=1;i<n;i++)f[T][i]=inf;
f[T][n]=0;
for(int k=T-1;k>=0;k--){
for(int i=1;i<=n;i++){
f[k][i]=f[k+1][i]+1;
if(i<n&&train[k][i][0]&&k+t[i]<=T){
f[k][i]=min(f[k+t[i]][i+1],f[k][i]);
}
if(i>1&&train[k][i][1]&&k+t[i-1]<=T){
f[k][i]=min(f[k+t[i-1]][i-1],f[k][i]);
}
}
}
printf("Case Number %d: ",++kase);
if(f[0][1]>=inf)puts("impossible");
else printf("%d\n",f[0][1]);
}
}
uva1025

## 48.传纸条

$f[i][j][k][l]=max(f[i][j-1][k-1][l],max(f[i-1][j][k][l-1],max(f[i][j-1][k][l-1],f[i-1][j][k-1][l])))+a[i][j]+a[k][l]$

#include <bits/stdc++.h>
using namespace std;
int n,m,a[100][100],f[51][51][51][51];
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
scanf("%d",&a[i][j]);
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
for(int k=1;k<=n;k++){
for(int l=j+1;l<=m;l++){
f[i][j][k][l]=max(f[i][j-1][k-1][l],max(f[i-1][j][k][l-1],max(f[i][j-1][k][l-1],f[i-1][j][k-1][l])))+a[i][j]+a[k][l];
}
}
}
}
printf("%d\n",f[n][m-1][n-1][m]);
}

## 49.书本整理

#include <bits/stdc++.h>
using namespace std;
struct node {
int h,w;
}a[1000];
int f[110][110],n,k;
//前i本书选了j本且以第i本结束
bool cmp(node a,node b){
return a.h<b.h;
}
#define inf 0x3f3f3f3f
int main(){
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++){
scanf("%d%d",&a[i].h,&a[i].w);
}
sort(a+1,a+n+1,cmp);
for(int i=1;i<=n;i++){
f[i][1]=0;
for(int j=2;j<=i;j++){
f[i][j]=inf;
for(int k=j-1;k<i;k++){
f[i][j]=min(f[i][j],f[k][j-1]+abs(a[i].w-a[k].w));
}
}
}
int ans=inf;
for(int i=n-k;i<=n;i++){
ans=min(f[i][n-k],ans);
}
printf("%d\n",ans);
}

## 50.[Zjoi2004]Lunch 午餐

50题了！

>_<！

posted @ 2018-07-10 16:17  henry_y  阅读(9048)  评论(4编辑  收藏  举报