hdu 6103 Kirinriki dp+二分 或 尺取法

来源:互联网 发布:mac版word删除空白页 编辑:程序博客网 时间:2024/06/05 20:20

题目连接:hdu 6103
题意:找出整个字符串中两个相同长度,但不重叠的连续字串,求满足他们的距离小于等于m的最长长度。
二分+dp应该也是能写的,但是我错了,应该是dp没写好, 队友写的dp过了。

#include<bits/stdc++.h>using namespace std;const int MAXN = 5005;char str[20005];short int dp[MAXN][MAXN];bool judge(int n, int x, int len){    for(int i=0; i<=len-x-x; ++i)    {        for(int j=i+2*x-1; j<len; ++j)        {            if(i+x>j-x)            {                if(dp[i][j]<=n)                    return true;            }            else            {                if(dp[i][j]-dp[i+x][j-x]<=n)                    return true;            }        }    }    return false;}int main(){    int t, n;    scanf("%d", &t);    while(t--)    {        scanf("%d",&n);        scanf(" %s", str);        int len=strlen(str);        //memset(dp, 0, sizeof(dp));        int l, r;        for(int i=0; i<len; ++i)        {            l=i;            dp[i][i]=0;            r=i+1;            dp[l][r]=dp[l][r]+abs(str[l]-str[r]);            l--;            r++;            while(l>=0&&r<len)            {                dp[l][r]=dp[l+1][r-1]+abs(str[l]-str[r]);                l--, r++;            }        }        for(int i=0; i<len; ++i)        {            l=i-1;            r=i+1;            while(l>=0&&r<len)            {                dp[l][r]=dp[l+1][r-1]+abs(str[l]-str[r]);                l--, r++;            }        }//        for(int i=0; i<len; ++i)//        {//            for(int j=i; j<len; ++j)//            {//                printf("%d%c", dp[i][j], j==len-1?'\n':' ');//            }//        }        l=0, r=len;        while(l<r)        {            int mid=(l+r+1)>>1;            if(judge(n, mid, len))                l=mid;            else                r=mid-1;        }        printf("%d\n", l);    }    return 0;}

以上是错误代码。
以下为AC代码

#include<bits/stdc++.h>using namespace std;typedef long long LL;typedef unsigned long long ULL;const int N = 100011;short dp[5005][5005];char ch[5500];int k;int m;bool panduan(int l){    int i,j;    for(i=1; i+2*l-1<=k; i++)        for(j=k; j-2*l+1>=i; j--)        {            if(dp[i][j]-dp[i+l][j-l]<=m)                return true;        }    return false;}int main(){    int t;    scanf("%d",&t);    while(t--)    {        scanf("%d",&m);        scanf("%s",ch+1);        k=strlen(ch+1);        int i,j;        for(i=1; i<k; i++)            dp[i][i]=0,dp[i][i+1]=abs(ch[i]-ch[i+1]);        for(i=3; i<=k; i++)        {            for(j=1; j+i-1<=k; j++)                dp[j][j+i-1]=dp[j+1][j+i-2]+abs(ch[j]-ch[j+i-1]);        }        int l=0,r=k/2;        int m;        while(l<r)        {            m=(l+r+1)>>1;            if(!panduan(m))                r=m-1;            else l=m;        }        printf("%d\n",l);    }    return 0;}

看了网上写的, 感觉当时。。好傻

#include<bits/stdc++.h>using namespace std;const int MAXN = 20005;char str[MAXN];int ans, len, m;void solve(int x, int y){    int l=0, r=0, sum=0;    while(x-r>=0&&y+r<len)    {        if(sum+abs(str[x-r]-str[y+r])<=m)        {            sum+=abs(str[x-r]-str[y+r]);            r++;            ans=max(ans, r-l);        }        else        {            sum-=abs(str[y+l]-str[x-l]);            l++;            ans=max(ans,r-l);        }    }}int main(){    int T;    scanf("%d",&T);    while(T--)    {        scanf("%d", &m);        scanf("%s", str);        ans=0;        len = strlen(str);        for(int i=0; i<len; ++i)        {            solve(i, i+1);            solve(i-1,i+1);        }        printf("%d\n", ans);    }    return 0;}
原创粉丝点击