poj 간단한 dp문제 몇 개

16914 단어 단순poj300문제dp

제목:poj1836


제목: 수열을 먼저 점차적으로 늘린 다음에 점차 줄이는 형식을 구하려면 빼야 할 숫자 개수를 구한다.물론 직접 체감하거나 체감하기만 하고 체감하지 않을 수도 있다.분석: 가장 긴 점증자 서열의 방법으로 구한 다음에 두 개의 기점의 위치를 일일이 열거하면 된다.
#include
#include
#include
using namespace std;
const int INF=1e8;
const int N=1000+9;
void LIS(int n,int d[],double g[],double A[]) //Nlog(N)
{
    for(int i=1;i<=n;i++)g[i]=INF;
    for(int i=0;iint k=lower_bound(g+1,g+1+n,A[i])-g;
        d[i]=k;
        g[k]=A[i];
    }
}
int d1[N],d2[N];
double a[N],b[N],g[N];
int n;
int main()
{
   // freopen("f.txt","r",stdin);
    scanf("%d",&n);
    for(int i=0;iscanf("%lf",&a[i]),b[n-i-1]=a[i]; //b    
    LIS(n,d1,g,a);
    LIS(n,d2,g,b);
    int maxn=0;
    for(int i=0;ifor(int j=0;j1;j++)maxn=max(maxn,d1[i]+d2[j]);
    printf("%d
"
,n-maxn); return 0; }

제목:poj 1260


제목: 몇 종류의 진주와 그것들의 단가를 제시하고, 최소한의 돈으로 같은 수량의 같은 품질의 진주를 살 수 있도록 요구한다.[어떤 종류의 진주 n개(가격은 p)를 사더라도 (n+10)*p의 돈을 지불해야 한다. 즉, 10*p를 추가로 지불해야 한다. 분석: f[i]는 제i개 품목까지 최소 비용을 지불해야 한다는 뜻이다.그럼 f[i]=min {f[j]+(num[j+1]+num[j+2]+...+num[i])*p[i]}(j#include #include #include using namespace std; const int INF=1e8; const int N=100+9; /* f[i] i 。 f[i]=min{ f[j]+(num[j+1]+num[j+2]+....+num[i])*p[i] } */ int n,ans; int num[N],p[N],f[N]; int main() { // freopen("f.txt","r",stdin); int T;scanf("%d",&T); while(T--){ ans=INF; scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d%d",&num[i],&p[i]); } f[0]=0; for(int i=1;i<=n;i++){ int minn=INF,cnt=num[i]; for(int j=i-1;j>=0;j--){ minn=min(minn,f[j]+(cnt+10)*p[i]); cnt+=num[j]; } f[i]=minn; } printf("%d
"
,f[n]); } return 0; }

poj 1080


제목: LCS 변형 문제는 LCS의 사상에 따라 dp방정식을 추측하면 된다.
#include
#include
using namespace std;
const int mod=998244353;
const int N=111;
int w[300][300],f[N][N];
char s1[111],s2[111];
int main()
{
    //freopen("f.txt","r",stdin);
    w['A']['A']=w['C']['C']=w['G']['G']=w['T']['T']=5;
    w['A']['C']=w['C']['A']=w['A']['T']=w['T']['A']=w['T']['-']=w['-']['T']=-1;
    w['A']['G']=w['G']['A']=w['C']['T']=w['T']['C']=w['G']['-']=w['-']['G']=-2;
    w['G']['T']=w['T']['G']=-2;
    w['A']['-']=w['-']['A']=w['C']['G']=w['G']['C']=-3;
    w['C']['-']=w['-']['C']=-4;
    int T;scanf("%d",&T);
    while(T--){
        int n1;scanf("%d%s",&n1,s1+1);
        int n2;scanf("%d%s",&n2,s2+1);
        int ans=0;
        f[0][0]=0;
        for(int i=1;i<=n1;i++)f[i][0]=f[i-1][0]+w[s1[i]]['-'];
        for(int j=1;j<=n2;j++)f[0][j]=f[0][j-1]+w['-'][s2[j]];
        for(int i=1;i<=n1;i++){
            for(int j=1;j<=n2;j++){
                f[i][j]=f[i-1][j-1]+w[s1[i]][s2[j]];
                f[i][j]=max(f[i][j],f[i-1][j]+w[s1[i]]['-']);
                f[i][j]=max(f[i][j],f[i][j-1]+w['-'][s2[j]]);
            }
        }
        printf("%d
"
,f[n1][n2]); } return 0; }

poj 1159


제목: 문자열을 주고 최소한 몇 글자를 삽입하면 답장열을 구성할 수 있냐고요?분석: 정열과 역열의 가장 긴 공통 서열을 구하면 가장 일치하고 가장 적게 삽입된 것은 n-LCS이다.이 문제 n<=5000, int f[N][N]로 메모리를 초과할 수 있고 short로 바꿀 수도 있고 스크롤 그룹으로 바꿀 수도 있습니다.
#include
#include
#include
using namespace std;
const int N=5001;
char a[N],b[N];
short f[2][N];
int n;
int main()
{
    //freopen("f.txt","r",stdin);
    scanf("%d%s",&n,a+1);
    for(int i=1;i<=n;i++)b[n-i+1]=a[i];
    f[0][0]=0;
    int k=0;
    for(int i=1;i<=n;i++){
        k=1^k;
        for(int j=1;j<=n;j++){
            if(a[i]==b[j])f[k][j]=f[k^1][j-1]+1;
            else f[k][j]=max(f[k^1][j],f[k][j-1]);
        }
    }
    printf("%d
"
,n-f[k][n]); return 0; }

poj 2479


제목: 가장 큰 두 단락의 연속 서열과 정수 서열을 구합니다.분석:poj1836 문제와 유사하게 왼쪽에서 시작하는 최대 서열과 f[i], 오른쪽에서 시작하는 최대 서열과 d[i]를 구한다.그리고 중점을 일일이 열거하면 된다.f[i]는 왼쪽에서 i점까지의 가장 큰 연속 서열을 표시하고 d[i]는 오른쪽에서 i점까지의 가장 큰 연속 서열과
#include
#include
#include
using namespace std;
const int INF=5e8;
const int N=50001;
int f[N],d[N],a[N];
int n;
int main()
{
    //freopen("f.txt","r",stdin);
    int T;scanf("%d",&T);
    while(T--){
        memset(f,0,sizeof(f));
        memset(d,0,sizeof(d));
        scanf("%d",&n);
        for(int i=1;i<=n;i++)scanf("%d",&a[i]);
        int sum=a[1],maxn=a[1];
        f[1]=a[1];
        for(int i=2;i<=n;i++){
            if(sum<0)sum=0;
            sum+=a[i],maxn=max(sum,maxn);
            f[i]=maxn;
        }
        sum=maxn=d[n]=a[n];
        for(int i=n-1;i>=1;i--){
            if(sum<0)sum=0;
            sum+=a[i],maxn=max(sum,maxn);
            d[i]=maxn;
        }
        int ans=-INF;
        for(int i=1;i1]);
        }
        printf("%d
"
,ans); } return 0; } /* 3 10 1 -1 2 2 3 -3 4 -4 5 -5 2 1 -1 3 1 -1 2 */

좋은 웹페이지 즐겨찾기