日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

HDU 1693(状态压缩 插头DP)

發布時間:2025/4/5 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 HDU 1693(状态压缩 插头DP) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

?

我們引用國家隊2008年陳丹琦的大作——《基于連通性狀態壓縮的動態規劃問題》,上面對于插頭、輪廓線的概念有詳細的解釋,不再贅述。

?

我們使用一個三維數組,前兩維表示所在的格子,后一維表示輪廓線的狀況,值為方案數。

?

在每一行開始前,我們需要把上一行最右的輪廓線轉換為這一行最左的輪廓線,因此執行一次左移操作(實際上輪廓線是進行了向右的一次滑動)

?

?

?

然后枚舉所在單元格對每個輪廓線的影響 在論文中我們可以發現輪廓線總是包圍一個格子的上部分和左部分 我們認為如果有通路與輪廓線重合則為1否則為0

?

?

?

?

因此很容易想象出來(當然也可以看論文)各個狀態之間的轉移關系 對于可通行的格子 分部分覆蓋和全部覆蓋以及全部不覆蓋的情況討論

?

對不可通行的格子必須將不可能的覆蓋方案置為0 到最后的結果就是所求的方案了即dp[m][n][0]

?

感謝DK大牛的指導 本人5天來的苦思冥想終于得到了成果 1693 0ms 排行統計第一....

?

以下為本人代碼:

?

?

#include?<iostream>
using?namespace?std;
typedef?__int64?LL;
LL?dp[
12][12][1<<12];
long?hash[12][12];

int?main()
{
????
long?T;
????
long?b=1;
????scanf(
"%ld",&T);
????
while?(T--)
????{
????????
long?i,j,k,m,n;
????????scanf(
"%ld?%ld",&m,&n);
????????
for?(i=1;i<=m;++i)
????????{
????????????
for?(j=1;j<=n;++j)
????????????{
????????????????scanf(
"%ld",&hash[i][j]);
????????????}
????????}

????????dp[
0][n][0]=1;

????????
for?(i=1;i<=m;++i)
????????{
????????????
long?len=1<<n;
????????????
for?(j=0;j<len;++j)
????????????{
????????????????dp[i][
0][j<<1]=dp[i-1][n][j];
????????????}

????????????
????????????
for?(j=1;j<=n;++j)
????????????{
????????????????len
=(1<<n<<1);
????????????????
for(k=0;k<len;++k)
????????????????{
????????????????????
long?p=1<<j;
????????????????????
long?q=p>>1;
????????????????????
????????????????????
bool?x=p&k;
????????????????????
bool?y=q&k;

????????????????????
if?(hash[i][j])
????????????????????{
????????????????????????dp[i][j][k]
=dp[i][j-1][k^p^q];
????????????????????????
if?(x!=y)
????????????????????????{
????????????????????????????dp[i][j][k]
+=dp[i][j-1][k];
????????????????????????}
????????????????????}
????????????????????
else
????????????????????{
????????????????????????
if?(x==0&&y==0)
????????????????????????{
????????????????????????????dp[i][j][k]
=dp[i][j-1][k];
????????????????????????}
????????????????????????
else
????????????????????????{
????????????????????????????dp[i][j][k]
=0;
????????????????????????}
????????????????????}
????????????????}
????????????}
????????}
????????printf(
"Case?%ld:?There?are?%I64d?ways?to?eat?the?trees.\n",b++,dp[m][n][0]);

????}
????
return?0;
}

?

?

以下為DK大人的sample代碼,我加上了注釋:

?

#include<iostream>
using?namespace?std;
int?mat[100][100];
__int64?dp[
12][12][1<<12];
int?main()
{
????
//?freopen("1.txt","r",stdin);
????int?zu;
????
int?g=1;
????scanf(
"%d",&zu);
????
while(zu--)
????{
????????
int?m,n;
????????scanf(
"%d%d",&m,&n);
????????
int?i,j,k;
????????
for(i=1;i<=m;i++)
????????????
for(j=1;j<=n;j++)
????????????????scanf(
"%d",&mat[i][j]);
????????????
//memset(dp,0,sizeof(dp));
????????????dp[0][n][0]=1;
????????????
for(i=1;i<=m;i++)
????????????{
????????????????
for(j=0;j<(1<<n);j++)
????????????????????dp[i][
0][j<<1]=dp[i-1][n][j];
????????????????
//把最右邊的去掉?把所有的狀態拉到下一行并進行合理的改變(注意最左邊的是低位所代表的數)?
????????????????
//上一行最右邊的邊格一定不與輪廓線重合?下一行最左邊的邊格也一定不與輪廓線重合?
????????????????
//所以進行的是上一行所有狀態(也就是輪廓線)向右的一次滑動
????????????????????for(j=1;j<=n;j++)//枚舉決策線的拐向
????????????????????{
????????????????????????
for(k=0;k<(1<<n<<1);k++)//枚舉輪廓線
????????????????????????{
????????????????????????????
int?p=1<<j;//第j個輪廓段(上)
????????????????????????????int?q=p>>1;//第j-1個輪廓段(左)
????????????????????????????bool?x=k&p;//左輪廓是否與通路相交
????????????????????????????bool?y=k&q;//上輪廓是否與通路相交
????????????????????????????
????????????????????????????
//判斷輪廓線在[i,j]為拐向時的分布?每個格子有1<<n<<1種?多階段決策
????????????????????????????
????????????????????????????
if(mat[i][j])//如果該單元可以通行
????????????????????????????{
????????????????????????????????dp[i][j][k]
=dp[i][j-1][k^p^q];//必然有一個通路連接上一個格的通路
????????????????????????????????if(x!=y)
????????????????????????????????????dp[i][j][k]
+=dp[i][j-1][k];//有一處新覆蓋則有另外的一種情況
????????????????????????????}
????????????????????????????
else//否則為障礙格子
????????????????????????????{
????????????????????????????????
if(x==0&&y==0)//通路與輪廓線不相交
????????????????????????????????????dp[i][j][k]=dp[i][j-1][k];//直接轉移
????????????????????????????????else
????????????????????????????????????dp[i][j][k]
=0;//通路與輪廓線相交的方案一定為0
????????????????????????????}
????????????????????????}
????????????????????}
????????????}
????????????printf(
"Case?%d:?There?are?%I64d?ways?to?eat?the?trees.\n",g++,dp[m][n][0]);
????}
????
return?0;
}?

轉載于:https://www.cnblogs.com/zhuangli/archive/2008/09/04/1283753.html

總結

以上是生活随笔為你收集整理的HDU 1693(状态压缩 插头DP)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。