题目传送门
C题:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int MaxN = 1005;
int dp[MaxN][MaxN];
int mymax (int a, int b)
{
return ((a > b) ? a : b);
}
int main()
{
char a[MaxN], b[MaxN];
while (~scanf("%s %s", a, b)){
int lena = strlen(a), lenb = strlen(b);
memset(dp,0, sizeof(dp));
/**********①**********/
for (int i=1; i<=lena; i++){
for (int j=1; j<=lenb; j++){
if (a[i-1] == b[j-1]) dp[i][j] = dp[i-1][j-1] + 1;
else dp[i][j] = mymax(dp[i-1][j], dp[i][j-1]);
}
}
/**********************/
printf ("%d\n", dp[lena][lenb]);
}
return 0;
}
①:
这一段本来是这样写的
for (int i=0; i<=lena; i++){
for (int j=0; j<=lenb; j++){
if (i == 0 || j ==0){
if (a[i] == b[j]) dp[i] =1 ;
else dp[i] = 0;
}
else{
if (a[i-1] == b[j-1]) dp[i][j] = dp[i-1][j-1] + 1;
else dp[i][j] = mymax(dp[i-1][j], dp[i][j-1]);
}
}
}
这样一直交不过,后来才发现有BUG如果a[0] = b[j], 那么dp[0][j+1],dp[0][j+2] 都应该是1,而按照第二种写法它们都变成了0,因此第二种写法是错误的。
E题
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int MaxN = 105;
int a[MaxN][MaxN];
int dp[MaxN][MaxN];
int dr[4] = {0, 0, -1, 1};
int dc[4] = {-1, 1, 0, 0};
int R, C;
bool ingrid(int row, int col)
{
return (0<=row && row<R && 0<=col && col<C);
}
int dfs (int row, int col);
int main()
{
scanf("%d %d", &R, &C);
for (int i=0; i<R; i++)
for (int j=0; j<C; j++)
scanf("%d",&a[i][j]);
memset(dp, 0, sizeof(dp));
int ans = 0;
for (int i=0; i<R; i++){
for (int j=0; j<C; j++){
dp[i][j] = dfs(i, j);
ans = max (ans, dp[i][j]);
//printf("%d ", dp[i][j]);
}
//printf("\n");
}
printf ("%d\n", ans);
}
int dfs (int row, int col)
{
if (dp[row][col]) return dp[row][col];
int nr, nc;
int temp[4] = {0};
for (int i=0; i<4; i++){
nr = row + dr[i];
nc = col + dc[i];
if (ingrid(nr, nc) && a[nr][nc]<a[row][col]){
temp[i] = dfs(nr,nc);
}
temp[i] += 1;
//if (a[row][col] == 19)printf (" temp[%d]=%d ", 0, temp[0]);
}
int re = 0;
//if (a[row][col] == 19) printf ("temp[0]=%d",temp[0]);
if (temp[0] > re){ re = temp[0];};
if (temp[1] > re) re = temp[1];
if (temp[2] > re) re = temp[2];
if (temp[3] > re) re = temp[3];
//if (a[row][col] == 19)printf(" re=%d ",re);
//if (!re) re = 1;
return re;
}
脑残,把temp[4] 放到全局变量里了,一直WA找不出原因。
F题:
//我的算法
//f[i][j]表示前i束花插入前j个瓶子所获得的最大价值,
//转移方程:f[i][j] = max(f[i-1][j-1], f[i-1][j-2],...) +a[i][j];
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int MaxN = 105;
int a[MaxN][MaxN];
int dp[MaxN][MaxN];
int f, v;
int search_max (int row, int col);
int main()
{
scanf("%d %d", &f, &v);
for (int i=0; i<f; i++)
for (int j=0; j<v; j++)
scanf("%d", &a[i][j]);
memset(dp, 0, sizeof(dp));
dp[0][0] = a[0][0];
int ans = -100, temp;
for (int j=v-1; j>f-2 &&j >-1; j--){
temp = search_max(f-1,j);
if (temp > ans) ans = temp;
}
/*for (int i=0; i<f; i++){
for (int j=0; j<v; j++)
printf ("%d ",dp[i][j]);
printf ("\n");
}*/
printf("%d\n", ans);
return 0;
}
int search_max (int row, int col)
{
if (row < 0) return 0;
if (row ==0 && col ==0) return a[0][0];
if (dp[row][col])
return dp[row][col];
int temp, maxi = -100;
for (int j=col-1; j>row-2&&j>-1; j--){
temp = search_max(row-1, j);
if (temp > maxi) maxi = temp;
}
temp = maxi + a[row][col];
//printf ("tmep=%d maxi=%d\n",temp,maxi);
dp[row][col] = temp;
return temp;
}
//题解算法
// dp[i][j]表示前i束花插入到前j个花瓶里所产生的最大的美学价值
// 转移方程:当j小于i时,连续赋值;超过之后,判断是否添加新的花即可
// (j <= i): dp[i][j] = dp[i - 1][j - 1] + a[i][j];
// (j > i ): dp[i][j] = max(dp[i - 1][j - 1] + a[i][j], dp[i][j - 1])
/******************************************************************************
* COPYRIGHT NOTICE
* Copyright (c) 2014 All rights reserved
* ----Stay Hungry Stay Foolish----
*
* @author :Shen
* @name :[NWPU][2014][TRN][6] F
* @file :G:\My Source Code\【ACM】训练\[NWPU][2014][TRN][6][0716]简单线性dp\F.cpp
* @date :2014/07/16 11:59
* @algorithm :DP
******************************************************************************/
#include <cmath>
#include <cstdio>
#include <string>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <algorithm>
using namespace std;
template<class T>inline bool updateMin(T& a, T b){ return a > b ? a = b, 1 : 0; }
template<class T>inline bool updateMax(T& a, T b){ return a < b ? a = b, 1 : 0; }
const int MaxN = 105;
const int INF = 100000;
int f, v;
int a[MaxN][MaxN], dp[MaxN][MaxN];
void solve()
{
for (int i = 1; i <= f; i++)
for (int j = 1; j <= v; j++)
scanf("%d", &a[i][j]);
memset(dp, 0, sizeof(dp));
for (int i = 1; i <= f; i++)
for (int j = 0; j <= v; j++)// 初值设置
dp[i][j] = -INF;
for (int i = 1; i <= f; i++)
for (int j = i; j <= v - f + i; j++)
dp[i][j] = max(dp[i][j - 1], dp[i - 1][j - 1] + a[i][j]);
printf("%d\n", dp[f][v]);
}
int main()
{
while (~scanf("%d%d", &f, &v)) solve();
return 0;
}
水平差很大
H题:
#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
const int MaxN = 5000 + 5;
char a[MaxN], b[MaxN];
int dp[2][MaxN];
int n;
int main()
{
scanf("%d", &n);
for (int i=1, j= n; i<=n; ++i,--j){
scanf(" %c", &a[i]);
b[j] = a[i];
}
memset(dp, 0, sizeof(dp));
//cout << a+1 <<" "<< b+1;
for (int i=1; i<=n; i++)
for (int j=1; j<=n; j++){
if(a[i] == b[j]) dp[i%2][j] = dp[(i-1)%2][j-1] + 1; //①
else dp [i%2][j] = max (dp[(i-1)%2][j], dp[i%2][j-1]);
//printf("%d\n",dp[i%2][j]);
}
/*for (int i=0; i<=n; i++){
for (int j=0; j<=n; j++)
printf ("%d ",dp[i][j]);
printf ("\n");
}
*/
int ans = n - dp[n%2][n];
printf("%d\n", ans);
return 0;
}
①:这里原来用了dp[MaxN][MaxN] 的数组,导致内存超限,后来参考网上代码,才解决了这个问题。
I题:
#include <stdio.h>
#include <stdlib.h>
#define size 2005
#define INIT 2147483646
int cmp(const void *a,const void *b)
{
return *(int *)a-*(int *)b;
}
int Min(int a,int b)
{
return a<b?a:b;
}
int dp[size][1005];
int main()
{
int n,k,i,j;
int val[size] = {0};
dp[0][0] = 0;
while (scanf("%d%d",&n,&k)!=EOF)
{
val[0] = 0;
for(i=1;i<=n;i++)
scanf("%d",&val[i]);
qsort(val+1,n,sizeof(val[0]),cmp);
for (i=0;i<=n;i++)
{
for(j=1;j<=k;j++)
dp[i][j] = INIT;
}
for (i=2;i<=n;i++)
{
for (j=1;j*2<=i;j++)
dp[i][j] = Min(dp[i-2][j-1]+(val[i]-val[i-1])*(val[i]-val[i-1]),dp[i-1][j]);
}
printf("%d\n",dp[n][k]);
}
return 0;
}
原来用递归写的,结果没问题,但是超时了,只好改用递推了。
K题:
可耻地参考了题解。。。。
状态:f[i][j] 表示第i时刻转移了j次所能得到的最多的苹果数。
转移方程:
i 时刻在第一颗树下(j % 2 == 0) f[i][j] = max(f[i-1][j-1], f[i-1][j]) + 2 - a[i];
i时刻在第二课树下(j % 2 == 1) f[i][j] = max(f[i-1][j-1], f[i-1][j]) + a[i] - 1;
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int MaxN = 1005;
int a[MaxN], dp[MaxN][35];
int main()
{
int m, n;
while (cin >> n >> m){
memset(dp, 0, sizeof(dp));
for (int i=0; i<n; i++){
scanf("%d", &a[i]);
dp[i][0] = dp[i-1][0] + 2 - a[i];
}
dp[0][0] = 2 - a[0];
dp[0][1] = a[0] - 1;
int temp;
for (int j=0; j<=m; j++){
temp = j % 2;
for (int i=1;i<n;i++){
if (temp){
dp[i][j] = max(dp[i-1][j-1], dp[i-1][j]) + a[i] - 1;
}
else if (j == 0);
else dp[i][j] = max(dp[i-1][j-1], dp[i-1][j]) + 2 - a[i];
}
}
/*for (int i=0; i<n; i++){
for (int j=0; j<=m; j++)
printf("%d ",dp[i][j]);
printf("\n");
}
*/
printf("%d\n",dp[n-1][m]);
}
return 0;
}
L题:
这道题过得真不容易,首先想到的是按到达的房间号排序,用贪心,每十分钟尽量多地搬,写了半天WA了,然后找到了一组比较逗比的数据:
6
25 200
50 350
340 370
240 390
210 390
显然对于这组数据,上面的算法计算出来的结果是错误的,然后。。。。。实在没办法了,又可耻地看了题解;
题解的算法是用数组room[i] 表示从i 房间经过的次数, 然后最大次数*10,就是结果,其中还有好多细节,就不说了。
代码:
#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
const int MaxN = 405;
int room[MaxN];
int main ()
{
int T;
scanf("%d", &T);
while (T--){
int n, st, End;
scanf("%d", &n);
memset(room, 0, sizeof(room));
for (int i=0; i<n; i++){
scanf("%d %d", &st, &End);
if (st % 2) st++;
if (End % 2) End++;
if (st > End){
int temp = st;
st = End;
End = temp;
}
for (int j=st; j<=End; j++){
++room[j];
}
}
int ans = 0;
for (int i=0; i<MaxN; i++){
if (room[i] > ans) ans = room[i];
}
printf("%d\n", ans * 10);
}
return 0;
}