内容敏感图像压缩
Background
在清华大学存活,你需要有极强的文献阅读能力……【该背景与本题无关】
Description
有一张N*M的方格纸,每一个格子上写了一个正整数,现在我们把方格纸首尾相连,组成一个高度为N,周长为M的圆柱体的侧表面。
现在你需要找到一个从上到下贯穿该圆柱侧表面的长度为N的路径,使得路径上的权值尽量小。其中,路径上相邻的两点必须是“八连通的”。
Input Format
第一行两个整数N,M。接下来若干行是一个N* M的矩阵
Output Format
一行一个整数,表示答案。
Sample Input
3 3
1 2 2
2 2 1
3 2 1
Sample Output
3
Constraint
·对于20%数据,min(N,M) = 1
·对于40%数据N,M <= 40
·对于约50%数据,路径不经过圆柱体侧表面。
·对于100%数据,N,M <= 3000
所以,这道题的名字有什么意义呢?可以考完试看一看题目后面附的文章。
错误代码0分
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
int n,i,j,k,m,a[3005][3005] = {30005},p,ans;
int main()
{
freopen("compress.in","r",stdin);
freopen("compress.out","w",stdout);
scanf("%d %d",&n,&m);
for(i = 1;i <= n;i++)
{
for(j = 1;j <= m;j++)
{
scanf("%d",&a[i][j]);
}
}
if(m != 1)
{
for(i = n - 1;i >= 1;i--)
{
for(j = m;j >= 1;j--)
{
if(j == 1)
{
p = min(a[i + 1][m] + a[i][j],a[i + 1][j] + a[i][j]);
a[i][j] = min(a[i + 1][j + 1] + a[i][j],p);
}
else if(j == m)
{
p = min(a[i + 1][1] + a[i][j],a[i + 1][j] + a[i][j]);
a[i][j] = min(a[i + 1][j - 1] + a[i][j],p);
}
else
{
p = min(a[i + 1][j - 1] + a[i][j],a[i + 1][j] + a[i][j]);
a[i][j] = min(a[i + 1][j + 1] + a[i][j],p);
}
}
}
ans = a[1][1];
for(i = 2;i <= m;i++)
{
ans = min(a[1][i],ans);
}
}
else
{
ans = 0;
for(i = 1;i <= n;i++)
{
ans = ans + a[i][1];
}
}
printf("%d",ans);
return 0;
}
正确答案:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAXN 3010
#define INF 0x3f3f3f3f
int dp[MAXN][MAXN*2];
int mat[MAXN][MAXN*2];
int nextInt() {
int ans=0;
char c = 0;
while (c=getchar(),c<'0'||c>'9');
while (ans = ans*10+c-'0',c=getchar(),c>='0' && c<='9');
return ans;
}//快速读入
int main() {
// freopen("compress.in","r",stdin);
// freopen("compress.out","w",stdout);
int n,m;
scanf("%d%d",&n,&m);
memset(mat,0x3f,sizeof(mat));//把每一个点都变成最大值
memset(dp,0x3f,sizeof(dp)); //把每个路径都变成最大值
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
{
int x;
x = nextInt();
//scanf("%d",&x);
mat[i][j] = mat[i][j+m] = x;//分环成列在复制一个放在右面
}
for (int j=1;j<=m;j++)
dp[0][j] = 0;//假设最上面有一层为0的
for (int i=1;i<=n;i++)
for (int j=1;j<=m*2;j++)
dp[i][j] = min(dp[i-1][j-1],min(dp[i-1][j],dp[i-1][j+1])) + mat[i][j];//枚举每一个点他只有三种可能来的方向取最小值
int ans = INF;
for (int j=1;j<=m*2;j++)
ans = min(ans,dp[n][j]);//把最后一行所有的尽可能的最小值再比较得出最最小的值
printf("%d\n",ans);//输出答案
return 0;
}
****其实这道题我应该只是错在了没有化环为列。
内容敏感图像压缩
给你一个矩阵让你找到一个路径dp方程组写对了
常数优化,开o2
这道题如果说是一个环的话怎么办
就是今天上午讲的化环为列
完完整整复制一遍在棋盘上跑就行
就是一个过两边的复制问题